Хрестоматия по программированию на Си в Unix




Системные вызовы и взаимодействие с UNIX. Хрестоматия по программированию на Си в Unix


6.10.1. Напишите программу pwd, определяющую полное имя текущего рабочего каталога. #define U42 определяет файловую систему с длинными именами, отсутствие этого флага с короткими (14 символов).

/* Команда pwd. * Текст getwd() взят из исходных текстов библиотеки языка Си. */ #include <stdio.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <dirent.h>

#define ediag(e,r) (e) /* * getwd() возвращает полное имя текущего рабочего каталога. * При ошибке возвращается NULL, а в pathname копируется сообщение * об ошибке. */ #ifndef MAXPATHLEN #define MAXPATHLEN 128 #endif

#define CURDIR "." /* имя текущего каталога */ #define PARENTDIR ".." /* имя родительского каталога */ #define PATHSEP "/" /* разделитель компонент пути */ #define ROOTDIR "/" /* корневой каталог */ #define GETWDERR(s) strcpy(pathname, (s)); #define CP(to,from) strncpy(to,from.d_name,DIRSIZ),to[DIRSIZ]='\0'

char *strcpy(char *, char *); char *strncpy(char *, char *, int); char *getwd(char *pathname); static char *prepend(char *dirname, char *pathname);

static int pathsize; /* длина имени */

#ifndef U42 char *getwd(char *pathname) { char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */ char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ dev_t rdev; /* root device number */ int fil = (-1); /* directory file descriptor */ ino_t rino; /* root inode number */ struct direct dir; /* directory entry struct */ struct stat d ,dd; /* file status struct */ /* d - "." dd - ".." | dname */ char dname[DIRSIZ+1]; /* an directory entry */

pathsize = 0; *pnptr = '\0'; if (stat(ROOTDIR, &d) < 0) { GETWDERR(ediag("getwd: can't stat /", "getwd: нельзя выполнить stat /")); return (NULL); } rdev = d.st_dev; /* код устройства, на котором размещен корень */ rino = d.st_ino; /* номер I-узла, представляющего корневой каталог */

for (;;) { if (stat(CURDIR, &d) < 0) { CantStat: GETWDERR(ediag("getwd: can't stat .", "getwd: нельзя выполнить stat .")); goto fail; } if (d.st_ino == rino && d.st_dev == rdev) break; /* достигли корневого каталога */ if ((fil = open(PARENTDIR, O_RDONLY)) < 0) { GETWDERR(ediag("getwd: can't open ..", "getwd: нельзя открыть ..")); goto fail; } if (chdir(PARENTDIR) < 0) { GETWDERR(ediag("getwd: can't chdir to ..", "getwd: нельзя перейти в ..")); goto fail; } if (fstat(fil, &dd) < 0) goto CantStat; if (d.st_dev == dd.st_dev) { /* то же устройство */ if (d.st_ino == dd.st_ino) { /* достигли корня ".." == "." */ close(fil); break; } do { if (read(fil, (char *) &dir, sizeof(dir)) < sizeof(dir) ){ ReadErr: close(fil); GETWDERR(ediag("getwd: read error in ..", "getwd: ошибка чтения ..")); goto fail; } } while (dir.d_ino != d.st_ino); CP(dname,dir);




Содержание  Назад  Вперед