8 ŚRODOWISKO SYSTEMU UNIX_________
Teraz jesteśmy już gotowi do napisania programu fsize. Jeżeli z atrybutów otrzymanych od funkcji stat wynika, że plik nie jest skorowidzem, to jego rozmiar mamy w zasięgu ręki i możemy od razu go wypisać. Jeżeli jednak plik jest skorowidzem, to musimy w tym skorowidzu przeglądać kolejno plik po pliku; każdy z tych plików może być podskorowidzem, zatem proces jest rekurencyjny.
Funkcja główna zajmuje się argumentami wywołania programu; każdy z tych argumentów jest przekazywany funkcji fsize.
#include <stdio.h>
#include <string.h>
#include ”syscalls.h”
#include <fcntl.h> /* znaczniki dla czytania i pisania */
#include <sys/types.h> /* definicje typów */
#include <sys/stat.h> /* struktura zwracana przez stat */
#include "dirent.h"
void fsize(char *);
/* wypisz rozmiary plików */ main(int argc, char **argv)
if (argc == 1) /* domyślnie: bieżący skorowidz */ fsize(”.”); else
while (--argc > 0) fsize(*++argv); return 0;
Funkcja fsize wypisuje rozmiary plików. Jeśli jednak plik jest skorowidzem, to fsize najpierw wywołuje funkcję dirwalk, która przetwarza wszystkie pliki w tym skorowidzu. Zwróć uwagę na to, jak skorzystano ze znaczników S_IFMT i S_IFDIR (pochodzących z nagłówka <sys/stat.h>) przy sprawdzeniu, czy dany plik jest skorowidzem. Szczególne znaczenie ma tu postawienie nawiasów, gdyż priorytet operatora bitowej koniunkeji & jest niższy niż priorytet operatora przyrównania ==.
int stat(char *, struct stat *);
void dirwalk(char *, void (*fcn)(char *));
/* fsize: wypisz rozmiar pliku name */ void fsize(char *name)
struct stat stbuf;
8.6 PRZYKŁAD - WYPISYWANIE ZAWARTOŚCI SKOROWIDZÓW
powered by
Mi si ol
if (stat(name, &stbuf) == -1) {
fprintf(stderr, "fsize: nie mogę znaleźć %s\n", name); return;
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
dirwalk(name, fsize); /* skorowidz: rekurencja */ printf(”%8ld %s\n”, stbuf.st_size, name);
Funkcja dirwalk jest ogólną procedurą, która stosuje pewną funkcję dla każdego pliku zawartego w skorowidzu. Procedura ta otwiera skorowidz i w pętli przetwarza kolejno każdy plik, wywołując dla niego daną funkcję. Na koniec dirwalk zamyka skorowidz i wraca do miejsca wywołania. Funkcja fsize wywołuje dirwalk dla każdego skorowidza, zatem obie te funkcje wywołują się nawzajem rekurencyjnie.
#define MAX_PATH 1024
I* dirwalk: zastosuj funkcję fen do wszystkich plików w dir */ void dirwalk(char *dir, void (*fcn) (char *))
char name[ MAX_PATH|;
Dirent *dp;
DIR *dfd;
if ((dfd = opendir(dir)) == NULL) {
fprintf(stderr, "dirwalk: nie mogę otworzyć %s\n”, dir); return;
while ((dp = readdir(dfd)) != NULL) { if (strcmp(dp->name, ”.”) == 0 || strcmp(dp->name, ”..”) == 0) continue; /* pomiń siebie i przodka */ if (strlen(dir) + strlen(dp->name) + 2 > sizeof(name)) fprintf(stderr, "dirwalk: za długa nazwa %s/%s\n", dir, dp->name);
else {
sprintf(name, ”%s/%s”, dir, dp->name);
(*fcn)(name);
closedir(dfd);
Język ANSI C 241