Milan Stephan
Fotografie & IT

Zurück zur SP1 Übersicht

links.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>

static void die(const char *msg) {
	perror(msg);
	exit(EXIT_FAILURE);
}

int main(void) {

	char *dirname = "."; // . = aktuelles Verzeichnis

	// Verzeichnis öffnen
	DIR *dir = opendir(dirname);
	if (!dir) {
		die(dirname);
	}

	// Die errno wird vor jedem readdir-Aufruf auf 0 gesetzt.
	// Dann wird readdir aufgerufen und das Ergebnis in d
	// geschrieben. Die Klammern um diese Zuweisung führen
	// dazu, dass das Ziel der Zuweisung (also "d") als
	// Schleifenbedingung geprüft wird.
	// Eine Alternative zu dieser Schreibweise ist am Ende
	// des Codes, siehe (*).
	struct dirent *d;
	while (errno = 0, (d = readdir(dir))) {

		// Informationen über die Datei mit lstat erhalten
		struct stat sb;
		if (lstat(d->d_name, &sb)) {
			perror(d->d_name);
			// Je nach Zielstellung kann man sich hier überlegen,
			// ob man das Programm komplett abbrechen möchte.
			continue;
		}

		// Daten aus dem "sb"-struct auswerten und prüfen, ob
		// die Datei ein Symlink ist. Falls nicht, bei der
		// nächsten Datei weitermachen.
		if (!S_ISLNK(sb.st_mode)) {
			continue;
		}

		// Wenn wir hier angekommen sind, ist die Datei ein Symlink.
		printf("%s\n", d->d_name);
	}

	// Hier kommen wir nach der Schleife hin, also wenn d == NULL.
	// Wenn hier die errno != 0 ist, dann wissen wir sicher, dass
	// readdir den Fehler geworfen hat.
	if (errno) {
		die(dirname);
	}

	// Verzeichnis schließen
	closedir(dir);
}

/*
	(*) Statt der kompakten Schreibweise bei der while-Schleife
	    könnte man das auch so schreiben:

	while (1) {
		errno = 0;
		struct dirent *d = readdir(dir);
		if (!d) {
			break;
		}
		...
	}

	Funktioniert auch, ist aber wesentlich mehr Schreibarbeit. :D
*/