Главная · Поиск книг · Поступления книг · 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 ... 30 31 32 33 34 35 36  37 38 39 40 41 42 43 ... 87
Совет: для каталога полезно иметь такие коды доступа:

    chmod o-w,+t каталог

В системах BSD используется, как уже было упомянуто,  формат  каталога  с  переменной
длиной  записей. Чтобы иметь удобный доступ к именам в каталоге, возникли специальные
функции чтения каталога: opendir, closedir, readdir. Покажем, как простейшая  команда
ls реализуется через эти функции.

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

    #include 
    #include 
    #include 

    int listdir(char *dirname){
        register struct dirent *dirbuf;
        DIR *fddir;
        ino_t dot_ino = 0, dotdot_ino = 0;

        if((fddir = opendir (dirname)) == NULL){
            fprintf(stderr, "Can't read %s\n", dirname);
            return 1;
        }
        /* Без сортировки по алфавиту */
        while ((dirbuf = readdir (fddir)) != NULL ) {
            if (dirbuf->d_ino == 0) continue;
            if (strcmp (dirbuf->d_name, "." ) == 0){
                    dot_ino = dirbuf->d_ino;
                    continue;
            } else if(strcmp (dirbuf->d_name, "..") == 0){
                    dotdot_ino = dirbuf->d_ino;
                    continue;
            } else printf("%s\n", dirbuf->d_name);
        }
        closedir (fddir);

        if(dot_ino    == 0) printf("Поврежденный каталог: нет имени \".\"\n");
        if(dotdot_ino == 0) printf("Поврежденный каталог: нет имени \"..\"\n");
        if(dot_ino && dot_ino == dotdot_ino)  printf("Это корневой каталог диска\n");

        return 0;
    }

    int main(int ac, char *av[]){
        int i;

        if(ac > 1) for(i=1; i < ac; i++) listdir(av[i]);
        else                             listdir(".");

        return 0;
    }

Обратите внимание, что тут не требуется добавление '\0' в  конец  поля  d_name,  пос-
кольку его предоставляет нам сама функция readdir().

6.1.4.  Напишите программу удаления файлов и каталогов,  заданных  в  argv.   Делайте
stat,  чтобы  определить тип файла (файл/каталог). Программа должна отказываться уда-
лять файлы устройств.
     Для удаления пустого каталога (не содержащего иных имен, кроме "." и "..")  сле-
дует использовать сисвызов
    rmdir(имя_каталога);
(если каталог не пуст - errno получит значение EEXIST); а для удаления обычных файлов
(не каталогов)
    unlink(имя_файла);
Программа должна запрашивать подтверждение на удаление  каждого  файла,  выдавая  его
имя, тип, размер в килобайтах и вопрос "удалить ?".

6.1.5.  Напишите функцию рекурсивного обхода дерева подкаталогов и печати  имен  всех
файлов в нем. Ключ U42 означает файловую систему с длинными именами файлов (BSD 4.2).

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

    /*#!/bin/cc -DFIND -DU42 -DMATCHONLY treemk.c match.c -o tree -lx
     * Обход поддерева каталогов (по мотивам Керниган & Ритчи).
     *              Ключи компиляции:
     * BSD-4.2 BSD-4.3                     -DU42
     * XENIX с канонической файл.сист.      ничего
     * XENIX с библиотекой  -lx            -DU42
     *      программа поиска файлов                          -DFIND
     *      программа рекурсивного удаления                  -DRM_REC
     *      программа подсчета используемого места на диске  БЕЗ_КЛЮЧА
     */
    #include 
    #include 
    #include 
    #include          /* для MAXPATHLEN */

    #if defined(M_XENIX) && defined(U42)
    # include   /* XENIX + U42 эмуляция */
    #else
    # include 
    # define stat(f,s) lstat(f,s)  /* не проходить по символьным ссылкам */
    # define d_namlen d_reclen
    #endif

    /* проверка: каталог ли это */
    #define  isdir(st) ((st.st_mode & S_IFMT) == S_IFDIR)
    struct   stat st;               /* для сисвызова stat() */
    char     buf[MAXPATHLEN+1];     /* буфер для имени файла */

    #define FAILURE (-1)            /* код неудачи */
    #define SUCCESS   1             /* код успеха  */
    #define WARNING   0             /* нефатальная ошибка */
    /* Сообщения об ошибках во время обхода дерева: */
    #ifndef ERR_CANT_READ
    # define ERR_CANT_READ(name)  \
             fprintf( stderr, "\tНе могу читать \"%s\"\n", name), WARNING
    # define ERR_NAME_TOO_LONG()  \
             fprintf( stderr, "\tСлишком длинное полное имя\n" ), WARNING
    #endif

    /* Прототипы для предварительного объявления функций. */
    extern char *strrchr(char *, char);
    int directory (char *name, int level,
        int (*enter)(char *full, int level, struct stat *st),
        int (*leave)(char *full, int level),
        int (*touch)(char *full, int level, struct stat *st));
    /* Функции-обработчики enter, leave, touch должны
     * возвращать (-1) для прерывания просмотра дерева,
     * либо значение >= 0 для продолжения. */

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

    /* Обойти дерево с корнем в rootdir */
    int walktree (
        char *rootdir,      /* корень дерева */
        int (*enter)(char *full, int level, struct stat *st),
        int (*leave)(char *full, int level),
        int (*touch)(char *full, int level, struct stat *st)
    ){
        /* проверка корректности корня */
        if( stat(rootdir, &st) < 0 || !isdir(st)){
            fprintf( stderr, "\tПлохой корень дерева \"%s\"\n", rootdir );
            return   FAILURE;  /* неудача */
        }
        strcpy     (buf, rootdir);
        return act (buf, 0, enter, leave, touch);
    }

    /* Оценка файла с именем name.
     */
    int act (char *name, int level,
        int (*enter)(char *full, int level, struct stat *st),
        int (*leave)(char *full, int level),
        int (*touch)(char *full, int level, struct stat *st))
    {
        if (stat (name, &st) < 0)
            return WARNING; /* ошибка, но не фатальная      */
        if(isdir(st)){      /* позвать обработчик каталогов */
           if(enter)
              if( enter(name, level, &st) == FAILURE ) return FAILURE;
           return directory (name, level+1, enter, leave, touch);

        } else {            /* позвать обработчик файлов    */
           if(touch) return touch (name, level, &st);
           else      return SUCCESS;
        }
    }

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

    /* Обработать каталог: прочитать его и найти подкаталоги */
    int directory (char *name, int level,
        int (*enter)(char *full, int level, struct stat *st),
        int (*leave)(char *full, int level),
        int (*touch)(char *full, int level, struct stat *st))
    {
    #ifndef U42
        struct direct   dirbuf;
        int        fd;
    #else
        register struct dirent *dirbuf;
        DIR    *fd;
        extern DIR *opendir();
    #endif
        char   *nbp, *tail, *nep;
        int     i, retcode = SUCCESS;

    #ifndef U42
        if ((fd = open (name, 0)) < 0) {
    #else
        if ((fd = opendir (name)) == NULL) {
    #endif
            return ERR_CANT_READ(name);
        }

        tail = nbp = name + strlen (name);  /* указатель на закрывающий \0 */
        if( strcmp( name, "/" ))  /* если не "/" */
            *nbp++ = '/';
        *nbp = '\0';

    #ifndef U42
        if (nbp + DIRSIZ + 2 >= name + MAXPATHLEN) {
            *tail = '\0';
            return ERR_NAME_TOO_LONG();
        }
    #endif

    #ifndef U42
        while (read(fd, (char *) &dirbuf, sizeof(dirbuf)) == sizeof(dirbuf)){
            if (dirbuf.d_ino == 0)  /* стертый файл */
                continue;
            if (strcmp (dirbuf.d_name, "." ) == 0  ||
                strcmp (dirbuf.d_name, "..") == 0)  /* не интересуют */
                continue;
            for (i = 0, nep = nbp; i < DIRSIZ; i++)
                *nep++ = dirbuf.d_name[i];

    # else /*U42*/
        while ((dirbuf = readdir (fd)) != NULL ) {
            if (dirbuf->d_ino == 0)
                continue;
            if (strcmp (dirbuf->d_name, "." ) == 0  ||
                strcmp (dirbuf->d_name, "..") == 0)
                continue;
            for (i = 0, nep = nbp; i < dirbuf->d_namlen ; i++)
                *nep++ = dirbuf->d_name[i];
    #endif /*U42*/
            *nep = '\0';
            if( act(name, level,  enter, leave, touch) == FAILURE) {
                retcode = FAILURE; break;                          }
        }

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

    #ifndef U42
        close (fd);
    #else
        closedir(fd);
    #endif
        *tail = '\0';       /* восстановить старое name */

        if(retcode != FAILURE   &&   leave)
           if( leave(name, level) == FAILURE) retcode = FAILURE;
        return retcode;
    }

    /* -------------------------------------------------------------- */
    /* Disk Usage -- Оценка места, занимаемого файлами поддерева      */
    /* -------------------------------------------------------------- */
    /* Пересчет байтов в килобайты */
    #define KB(s)  (((s)/1024L) + ((s)%1024L ? 1L:0L))
    /* или #define KB(s)   (((s) + 1024L - 1) / 1024L)  */
    long size;                      /* общий размер     */
    long nfiles;                    /* всего файлов     */
    long ndirs;                     /* из них каталогов */
    #define WARNING_LIMIT 150L      /* подозрительно большой файл */

    static int du_touch (char *name, int level, struct stat *st){
         long sz;
         size += (sz = KB(st->st_size));  /* размер файла в Кб. */
         nfiles++;
    #ifndef TREEONLY
         if( sz >= WARNING_LIMIT )
            fprintf(stderr,"\tВнимание! \"%s\" очень большой: %ld Кб.\n",
                                          name,               sz);
    #endif /*TREEONLY*/
         return SUCCESS;
    }
    static int du_enter (char *name, int level, struct stat *st){
    #ifndef TREEONLY
         fprintf( stderr, "Каталог \"%s\"\n", name );
    #endif
         size += KB(st->st_size);  /* размер каталога в Кб. */
         nfiles++; ++ndirs; return SUCCESS;
    }
    long du (char *name){
         size = nfiles = ndirs = 0L;
         walktree(name, du_enter, NULL, du_touch );
         return size;
    }

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

    /* -------------------------------------------------------------- */
    /* Рекурсивное удаление файлов и каталогов                        */
    /* -------------------------------------------------------------- */
    int  deleted;    /* сколько файлов и каталогов удалено */
    static int recrm_dir (char *name, int level){
         if( rmdir(name) >= 0){ deleted++; return SUCCESS; }
         fprintf(stderr, "Не могу rmdir '%s'\n", name); return WARNING;
    }

    static int recrm_file(char *name, int level, struct stat *st){
         if( unlink(name) >= 0){ deleted++; return SUCCESS; }
         fprintf(stderr, "Не могу rm    '%s'\n", name); return WARNING;
    }
    int recrmdir(char *name){
        int ok_code; deleted = 0;
        ok_code = walktree(name, NULL, recrm_dir, recrm_file);
        printf("Удалено %d файлов и каталогов в %s\n", deleted, name);
        return ok_code;
    }

    /* -------------------------------------------------------------- */
    /* Поиск файлов с подходящим именем (по шаблону имени)            */
    /* -------------------------------------------------------------- */
    char *find_PATTERN;
    static int find_check(char *fullname, int level, struct stat *st){
        char *basename = strrchr(fullname, '/');
        if(basename) basename++;
        else         basename = fullname;
Предыдущая страница Следующая страница
1 ... 30 31 32 33 34 35 36  37 38 39 40 41 42 43 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама