LINUX.ORG.RU

Readdir, работа системного вызова


0

1

Привет! Преподаватель хочет, чтобы я знал подробную работу readdir, иначе зачет ставить не хочет
Сам уже не могу никак догадаться.

Исходник:

http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/g...
53 #include «lint.h»
54 #include <dirent.h>
55 #include <limits.h>
56 #include <errno.h>
57 #include «libc.h»
58
59 #ifdef _LP64
60
61 dirent_t *
62 readdir(DIR *dirp)
63 {
64 dirent_t *dp; /* -> directory data */
65 int saveloc = 0;
66
67 if (dirp->dd_size != 0) {
68 dp = (dirent_t *)(uintptr_t)&dirp->dd_buf[dirp->dd_loc];
69 saveloc = dirp->dd_loc; /* save for possible EOF */
70 dirp->dd_loc += (int)dp->d_reclen;
71 }
72 if (dirp->dd_loc >= dirp->dd_size)
73 dirp->dd_loc = dirp->dd_size = 0;
74
75 if (dirp->dd_size == 0 && /* refill buffer */
76 (dirp->dd_size = getdents(dirp->dd_fd,
77 (dirent_t *)(uintptr_t)dirp->dd_buf, DIRBUF)) <= 0) {
78 if (dirp->dd_size == 0) /* This means EOF */
79 dirp->dd_loc = saveloc; /* so save for telldir */
80 return (NULL); /* error or EOF */
81 }
82
83 return ((dirent_t *)(uintptr_t)&dirp->dd_buf[dirp->dd_loc]);
84 }

Описание структуры dirent: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/...

42 typedef struct dirent {
43 ino_t d_ino; /* «inode number» of entry */
44 off_t d_off; /* offset of disk directory entry */
45 unsigned short d_reclen; /* length of this record */
46 char d_name[1]; /* name of file */
47 } dirent_t;

Описание потока каталога: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/head/dirent.h

53 typedef struct {
54 int dd_fd; /* file descriptor */
55 int dd_loc; /* offset in block */
56 int dd_size; /* amount of valid data */
57 char *dd_buf; /* directory block */
58 } DIR; /* stream data from opendir() */

-------------------------------

Вопрос, вот идут файлы один за одним в буфере считываются, буфер фиксированного размера, что происходит, когда буфер заканчивается на середине файла, как решается проблема срыва буфера, и битой записи?

Желателен ответ и тут же аргументация(срока в коде) и по возможности объяснение.
Заранее благодарю!

голову включи цэ раз, два коли код выкладываешь, то надобно форматирование - без него читать просто невозможно, я было б и подсказал бы, очевидные вещи, например что еще посмотреть, да глаза парсить устали.

iov_vec_t
()
Ответ на: комментарий от rg-400

Спасибо, не знал.

Исходник:

http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/readdir.c

#include "lint.h"
#include <dirent.h>
#include <limits.h>
#include <errno.h>
#include "libc.h"
 
dirent_t *
readdir(DIR *dirp)
{
   dirent_t *dp; /* -> directory data */
   int saveloc = 0;
 
   if (dirp->dd_size != 0) 
   {
      dp = (dirent_t *)(uintptr_t)&dirp->dd_buf[dirp->dd_loc];
      saveloc = dirp->dd_loc; /* save for possible EOF */
      dirp->dd_loc += (int)dp->d_reclen;
   }
   if (dirp->dd_loc >= dirp->dd_size)
      dirp->dd_loc = dirp->dd_size = 0;
 
   if (dirp->dd_size == 0 && /* refill buffer */
   (dirp->dd_size = getdents(dirp->dd_fd, 
   (dirent_t *)(uintptr_t)dirp->dd_buf, DIRBUF)) <= 0) 
   {
      if (dirp->dd_size == 0) /* This means EOF */
         dirp->dd_loc = saveloc; /* so save for telldir */
      return (NULL); /* error or EOF */
   }
 
   return ((dirent_t *)(uintptr_t)&dirp->dd_buf[dirp->dd_loc]);
}
Описание структуры dirent: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/dirent.h#dirent_t
typedef struct dirent {
   ino_t d_ino; /* "inode number" of entry */
   off_t d_off; /* offset of disk directory entry */
   unsigned short d_reclen; /* length of this record */
   char d_name[1]; /* name of file */
} dirent_t;
Описание потока каталога: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/head/dirent.h
typedef struct {
   int dd_fd; /* file descriptor */
   int dd_loc; /* offset in block */
   int dd_size; /* amount of valid data */
   char *dd_buf; /* directory block */
} DIR; /* stream data from opendir() */

icebald
() автор топика
Ответ на: комментарий от icebald
   if (dirp->dd_size == 0 && /* refill buffer */
   (dirp->dd_size = getdents(dirp->dd_fd, 
   (dirent_t *)(uintptr_t)dirp->dd_buf, DIRBUF)) <= 0) 

на первый взгляд getdents следит за тем, чтобы в dd_buf было достаточно валидных dirent

xydo ★★
()
Ответ на: комментарий от xydo

Вопрос то в том,что происходит,когда буфер заканчивается на середине файла,как решается проблема срыва буфера,и битой записи?

icebald
() автор топика
Ответ на: комментарий от icebald

какой буфер и какой файл? Спроси у гугля про переполнение буфера.

rg-400
()
Ответ на: комментарий от icebald

Структуры dirent имеют переменную длину. getdents() возвращает количество байтов, соответствующее полностью прочитанным записям - число, меньшее, чем переданный размер буфера (man getdents). Дальше поймёте сами?

Sorcerer ★★★★★
()
Ответ на: комментарий от Sorcerer

А что getdents делает, если буфер закончится на середине какой-нибудь записи в каталоге? как в этом случае перезаполняется буфер? Возникает проблема битой записи? Как она решается непонятно...

icebald
() автор топика
Ответ на: комментарий от icebald

В этом случае getdents, очевидно, оставляет файловый курсор на начале записи, которая не помещается в буфер, чтобы при следующем вызове с пустым буфером прочитать её целиком вместе со следующими записями.

Sorcerer ★★★★★
()
Ответ на: комментарий от Sorcerer

А мы узнаем о конце файла, начав читать запись, или дойдя в таком случае до конца буфера? Нельзя же файловый курсор назад отматывать.

icebald
() автор топика
Ответ на: комментарий от icebald

Про lseek забыл, последняя фраза абсурдная...

А вот в где мы узнаем о конце записи? Начав читать её, или только когда подойдем к концу буфера?

icebald
() автор топика
Ответ на: комментарий от Sorcerer

В этом случае getdents, очевидно, оставляет файловый курсор на начале записи, которая не помещается в буфер, чтобы при следующем вызове с пустым буфером прочитать её целиком вместе со следующими записями.

Вообщем как экспериментально проверить, так ли это?

icebald
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.