Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

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

Предыдущая страница Следующая страница
1 ... 43 44 45 46 47 48 49  50 51 52 53 54 55 56 ... 87

Для того, чтобы поместить корневой каталог файловой  системы,  находящейся  на  диске
/dev/hd1, вместо каталога /mnt/hd1 уже "собранной" файловой системы, мы должны издать
сисвызов

    mount("/dev/hd1", "/mnt/hd1", 0);

Для отключения смонтированной файловой системы мы должны вызвать

    umount("/dev/hd1");

(каталог, к которому она смонтирована, уже числится в таблице ядра, поэтому его зада-
вать не надо).  При монтировании все содержимое каталога /mnt/hd1 станет недоступным,
зато при обращении к имени /mnt/hd1 мы на самом деле доберемся до (безымянного)  кор-
невого  каталога на диске /dev/hd1.  Такой каталог носит название mount point и может
быть выявлен по тому признаку, что "." и ".." в нем лежат на разных устройствах:

    struct stat st1, st2;
    stat("/mnt/hd1/.", &st1); stat("/mnt/hd1/..", &st2);
    if( st1.st_dev != st2.st_dev) ... ; /*mount point*/

Для st1 поле st_dev означает код устройства /dev/hd1, а для st2 - устройства,  содер-
жащего  корневую  файловую  систему.  Операции монтирования и отмонтирования файловых
систем доступны только суперпользователю.

     И напоследок - сравнение структур I-узла.

            на диске        в памяти        в вызове stat
                    

А. Богатырев, 1992-95                  - 252 -                              Си в UNIX

            struct dinode   struct inode    struct stat

         // коды доступа и тип файла
    ushort  di_mode         i_mode          st_mode
         // число имен файла
    short   di_nlink        i_nlink         st_nlink
         // номер I-узла
    ushort   ---            i_number        st_ino
         // идентификатор владельца
    ushort  di_uid          i_uid           st_uid
         // идентификатор группы владельца
    ushort  di_gid          i_gid           st_gid
         // размер файла в байтах
    off_t   di_size         i_size          st_size
         // время создания
    time_t  di_ctime        i_ctime         st_ctime
         // время последнего изменения (write)
    time_t  di_mtime        i_mtime         st_mtime
         // время последнего доступа (read/write)
    time_t  di_atime        i_atime         st_atime
         // устройство, на котором расположен файл
    dev_t     ---           i_dev           st_dev
         // устройство, к которому приводит спец.файл
    dev_t     ---           i_rdev          st_rdev
         // адреса блоков
    char    di_addr[39]     i_addr[]
         // счетчик ссылок на структуру в ядре
    cnt_t                   i_count
         //                 и кое-что еще

Минусы означают, что данное поле не хранится на диске, а вычисляется ядром. В  совре-
менных версиях UNIX могут быть легкие отличия от вышенаписанной таблицы.

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

А. Богатырев, 1992-95                  - 253 -                              Си в UNIX

    /* Команда pwd.
     * Текст getwd() взят из исходных текстов библиотеки языка Си.
     */
    #include 
    #include 
    #include 
    #include 
    #include 
    #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-узла, представляющего корневой каталог */

А. Богатырев, 1992-95                  - 254 -                              Си в UNIX

            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);

                    } else  /* ".." находится на другом диске: mount point */

                            do {
                                    if (read(fil, (char *) &dir,
                                        sizeof(dir)) < sizeof(dir))
                                            goto ReadErr;
                                    if( dir.d_ino == 0 )    /* файл стерт */
                                            continue;
                                    CP(dname,dir);
                                    if (stat(dname, &dd) < 0) {
                                            sprintf (pathname, "getwd: %s %s",
                                                     ediag ("can't stat",
                                                "нельзя выполнить stat"), dname);
                                            goto fail;
                                    }
                            } while(dd.st_ino != d.st_ino ||
                                    dd.st_dev != d.st_dev);
                    close(fil);
                    pnptr = prepend(PATHSEP, prepend(dname, pnptr));
            }

А. Богатырев, 1992-95                  - 255 -                              Си в UNIX

            if (*pnptr == '\0')             /* текущий каталог == корневому */
                    strcpy(pathname, ROOTDIR);
            else {
                    strcpy(pathname, pnptr);
                    if (chdir(pnptr) < 0) {
                            GETWDERR(ediag("getwd: can't change back to .",
                                           "getwd: нельзя вернуться в ."));
                            return (NULL);
                    }
            }
            return (pathname);

    fail:
            close(fil);
            chdir(prepend(CURDIR, pnptr));
            return (NULL);
    }

    #else /* U42 */
    extern char   *strcpy ();
    extern DIR    *opendir();

    char   *getwd (char *pathname)
    {
        char    pathbuf[MAXPATHLEN];/* temporary pathname buffer */
        char   *pnptr = &pathbuf[(sizeof pathbuf) - 1];/* pathname pointer */
        char   *prepend ();         /* prepend dirname to pathname */
        dev_t rdev;                 /* root device number */
        DIR * dirp;                 /* directory stream */
        ino_t rino;                 /* root inode number */
        struct dirent  *dir;        /* directory entry struct */
        struct stat d,
                    dd;             /* file status struct */

        pathsize = 0;
        *pnptr = '\0';
        stat (ROOTDIR, &d);
        rdev = d.st_dev;
        rino = d.st_ino;

        for (;;) {
            stat (CURDIR, &d);

            if (d.st_ino == rino && d.st_dev == rdev)
                break;              /* reached root directory */

            if ((dirp = opendir (PARENTDIR)) == NULL) {
                GETWDERR ("getwd: can't open ..");
                goto fail;
            }
            if (chdir (PARENTDIR) < 0) {
                closedir (dirp);
                GETWDERR ("getwd: can't chdir to ..");
                goto fail;
            }

А. Богатырев, 1992-95                  - 256 -                              Си в UNIX

            fstat (dirp -> dd_fd, &dd);
            if (d.st_dev == dd.st_dev) {
                if (d.st_ino == dd.st_ino) {
                /* reached root directory */
                    closedir (dirp);
                    break;
                }
                do {
                    if ((dir = readdir (dirp)) == NULL) {
                        closedir (dirp);
                        GETWDERR ("getwd: read error in ..");
                        goto fail;
                    }
                } while (dir -> d_ino != d.st_ino);
            }

            else
                do {
                    if ((dir = readdir (dirp)) == NULL) {
                        closedir (dirp);
                        GETWDERR ("getwd: read error in ..");
                        goto fail;
                    }
                    stat (dir -> d_name, &dd);
                } while (dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
            closedir (dirp);
            pnptr = prepend (PATHSEP, prepend (dir -> d_name, pnptr));
        }

        if (*pnptr == '\0')         /* current dir == root dir */
Предыдущая страница Следующая страница
1 ... 43 44 45 46 47 48 49  50 51 52 53 54 55 56 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама