2010-03-20 2 views
3

Я пытаюсь решить упражнение из K & R; это касается чтения каталогов. Эта задача зависит от системы, поскольку она использует системные вызовы. В книге примеров авторы говорят, что их пример написан для версии 7 и систем System V UNIX и что они использовали информацию каталога в заголовке < SYS/dir.h>, который выглядит следующим образом:Чтение каталога

#ifndef DIRSIZ 
#define DIRSIZ 14 
#endif 
struct direct { /* directory entry */ 
    ino_t d_ino;   /* inode number */ 
    char d_name[DIRSIZ]; /* long name does not have '\0' */ 
}; 

На эта система использует «struct direct» в сочетании с функцией «read» для извлечения записи в каталоге, которая состоит из имени файла и номера inode.

..... 
struct direct dirbuf; /* local directory structure */ 
while(read(dp->fd, (char *) &dirbuf, sizeof(dirbuf) 
       == sizeof(dirbuf) { 
    ..... 
} 
..... 

Я предполагаю, что это прекрасно работает на системах UNIX и Linux, но то, что я хочу сделать, это изменить это, так что работает на Windows XP.

Есть ли какая-либо структура в Windows, например, «struct direct», поэтому я могу использовать ее с функцией «read» и если есть имя заголовка, где определено значение ?

Или, может быть, Windows требует совершенно другого подхода?

ответ

2

В окнах ничего подобного нет. Если вы хотите перечислить каталог в Windows, вы должны использовать API FindFirstFile/FindNextFile.

+0

Или использовать Cygwin/MinGW. – pajton

+0

Как-то я не думаю, что создание приложения Windows, зависящего от библиотеки Unix Emulation, является хорошим выбором дизайна для нового кода. Кроме того, MinGW не делает ничего, чтобы решить эту проблему. Вы не можете открывать файлы каталога с помощью MinGW. Cygwin может поддерживать некоторые подобные вещи, но MinGW этого не делает. –

+0

Хорошо, но Палман заявил в вопросе, что он решает упражнения из K & R. Поэтому я думаю, что Cygwin для этого очень разумный выбор. Я согласен с вами в том, что использование Cygwin для создания производственного приложения не будет такой полезной идеей. – pajton

1

Да, это работает только с Linux/Unix. Однако, если вы просто играете, вы можете использовать Cygwin для создания программ в Windows, которые используют этот Unix API.

+0

Нет, я не хочу использовать Cygwin, я забыл написать это, когда писал первый пост, извините. – paleman

1

boost::filesystem::directory_iterator предоставляет переносимый эквивалент API FindFirstFile/FindNextFile для Windows и API-интерфейса POSIX readdir_r(). См. this tutorial.

Обратите внимание, что это C++ не обычный C.

+0

Мне нужен чистый C, но спасибо. – paleman

1

Интересно отметить, что вы используете K & R 1st Edition, с 1978 года, а не второе издание. Второе издание имеет разные структуры и т. Д., В тот момент в книге.

Этот код из первого издания больше не работает на многих Unix-подобных системах. Очень мало машин Unix осталось с файловыми системами, которые ограничивают имена файлов до 14-символьного предела, и этот код работает только в этих системах. В частности, он не работает на MacOS X (10.6.2) или Solaris (10) или Linux (SuSE Linux Enterprise Edition 10, ядро ​​2.6.16.60-0.21-smp). С тестом код, показанный ниже, результат:

read failed: (21: Is a directory) 

Текущие выпуски POSIX явно разрешить реализацию, чтобы ограничить то, что вы можете сделать с помощью дескриптора файла открыт в каталоге. В принципе, его можно использовать в системных вызовах «fchdir()» и, возможно, нескольких родственников, но это все.

Чтобы прочитать содержимое каталога, вы должны использовать opendir() семейства функций, а затем readdir() и т.д. Второе издание K & R продолжает использовать эти системные вызовы вместо сырого open() и read() т.д.

В целом, не удивительно, что код более 30 лет назад работает не так, как раньше.


В Windows вы можете использовать POSIX подсистему или эмуляцию, что такие, как Cygwin или MingW, и в любом случае вам нужно будет использовать opendir() и readdir() семейство вызовов функций, а не прямой open() и read() в дескрипторе файла каталога.

Или вы можете использовать собственный Windows API, который ссылается на BillyONeal, FindFirstFile и родственники.


код теста:

#include <unistd.h> 
#include <stdio.h> 
#include <string.h> 
#include <fcntl.h> 
#include <errno.h> 

int main() 
{ 
    int fd = open(".", O_RDONLY); 
    if (fd != -1) 
    { 
     char buffer[256]; 
     ssize_t n = read(fd, buffer, sizeof(buffer)); 
     if (n < 0) 
     { 
      int errnum = errno; 
      printf("read failed: (%d: %s)\n", errnum, strerror(errnum)); 
     } 
     else 
      printf("read OK: %d bytes (%s)\n", (int)n, buffer); 
     close(fd); 
    } 
    return(0); 
} 
+0

Я читал эту книгу онлайн один раз, и было написано «2.nd edition» рядом с именем, у меня его нет в бумажной форме, так что я не знаю – paleman

+0

Интересно - делали то, что вы искали в прототипах использования ? Если это так, это был второй Эдн, а не 1-й. Но в моей копии 1-го Edn (p170) есть '' #define DIRSIZ 14/struct direct {ino_t d_ino; char d_name [DIRSIZ]; }; ''(и не упоминается' opendir() 'и т. д.). В моей копии 2-го Edn (помечено «Основано на проекте предлагаемого ANSI C» от ​​1988 года, 1-я печать) на p180 существует «#define NAME_MAX 14/typedef struct {long ino; char name [NAME_MAX + 1]; } Dirent; '' (и обсуждение 'opendir()' и др. Ваш код выглядит ближе к 1-му Edn, чем второе издание для меня, поэтому мой комментарий. –

+0

@paleman: Тогда это 2-е издание K & R. больше в «C Answer Book» (Tondo & Gimpel - http://www.amazon.com/C-Answer-Book-Clovis-Tondo/dp/0131098772)? Если это так, то это может содержать то, что вы показываете - I –

Смежные вопросы