2 a replacement for opendir/readdir/telldir/seekdir/closedir
11 #include <sys/types.h>
17 #define DIR_BUF_BITS 9
18 #define DIR_BUF_SIZE (1<<DIR_BUF_BITS)
20 #define O_DIRECTORY 0200000
26 char buf[DIR_BUF_SIZE];
29 _syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count)
31 struct dir_buf *rep_opendir(const char *dname)
34 d = malloc(sizeof(*d));
35 d->fd = open(dname, O_DIRECTORY | O_RDONLY);
45 struct dirent *rep_readdir(struct dir_buf *d)
49 if (d->ofs >= d->nbytes) {
50 d->seekpos = lseek(d->fd, 0, SEEK_CUR);
51 d->nbytes = getdents(d->fd, (struct dirent *)d->buf, DIR_BUF_SIZE);
54 if (d->ofs >= d->nbytes) {
57 de = (struct dirent *)&d->buf[d->ofs];
58 d->ofs += de->d_reclen;
59 if (d->ofs >= d->nbytes) {
60 d->seekpos = lseek(d->fd, 0, SEEK_CUR);
61 d->nbytes = getdents(d->fd, (struct dirent *)d->buf, DIR_BUF_SIZE);
67 off_t rep_telldir(struct dir_buf *d)
69 if (d->ofs >= d->nbytes) {
70 d->seekpos = lseek(d->fd, 0, SEEK_CUR);
74 return (d->seekpos << DIR_BUF_BITS) + d->ofs;
77 void rep_seekdir(struct dir_buf *d, off_t ofs)
79 d->seekpos = lseek(d->fd, ofs >> DIR_BUF_BITS, SEEK_SET);
80 d->nbytes = getdents(d->fd, (struct dirent *)d->buf, DIR_BUF_SIZE);
82 while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) {
83 if (rep_readdir(d) == NULL) break;
87 int rep_closedir(struct dir_buf *d)
101 test readdir/unlink pattern that OS/2 uses
102 tridge@samba.org July 2005
107 #define TESTDIR "test.dir"
109 #define FAILED() (fprintf(stderr, "Failed at %s:%d - %s\n", __FUNCTION__, __LINE__, strerror(errno)), exit(1), 1)
111 static void cleanup(void)
113 /* I'm a lazy bastard */
114 system("rm -rf " TESTDIR);
115 mkdir(TESTDIR, 0700) == 0 || FAILED();
118 static void create_files()
121 for (i=0;i<NUM_FILES;i++) {
123 snprintf(fname, sizeof(fname), TESTDIR "/test%04u.txt", i);
124 close(open(fname, O_CREAT|O_RDWR, 0600)) == 0 || FAILED();
130 int total_deleted = 0;
137 d = rep_opendir(TESTDIR);
139 chdir(TESTDIR) == 0 || FAILED();
141 /* skip past . and .. */
143 strcmp(de->d_name, ".") == 0 || FAILED();
145 strcmp(de->d_name, "..") == 0 || FAILED();
147 while ((de = rep_readdir(d))) {
148 off_t ofs = rep_telldir(d);
149 printf("Deleting %s at %d\n", de->d_name, (int)ofs);
150 unlink(de->d_name) == 0 || FAILED();
152 /* move one more position on */
155 /* seek to just after the first readdir() */
161 printf("Deleted %d files of %d\n", total_deleted, NUM_FILES);
163 chdir("..") == 0 || FAILED();
165 rmdir(TESTDIR) == 0 || FAILED();