From: "Tim Van Holder" To: Subject: Draft patch for opendir() extension Date: Mon, 25 Dec 2000 17:56:57 +0100 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="Windows-1252" X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400 Importance: Normal Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id LAA07056 Reply-To: djgpp-workers AT delorie DOT com Below is a patch to extend opendir() et al to support 'virtual files' introduced by the fsext mechanism (eg /dev/zero). The idea is that fsext modules register and deregister any files they handle. The registering/deregistering isn't yet implemented in this draft, as this probably requires more thought: i.e. do fsext functions know the name of the file they're working on after the initial open()? Probably not, so they'd need to register a fd/name combination instead of just a name, so they can properly deregister a file. Any and all suggestions are welcomed. This patch also fixes a bug in telldir/seekdir. telldir() returns the number of actual entries read and seekdir() calls readdir() that many times after doing a rewinddir(). But if the DIR has simulated dots (or with this patch, other simulated entries), those numbers do not match. *** /dev/null Mon Dec 25 17:51:34 2000 --- include/sys/fsextdir.h Mon Dec 25 17:29:02 2000 *************** *** 0 **** --- 1,33 ---- + /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ + + /* Written by Tim Van Holder. + * This file declares functions that allow fsext routines to + * register/deregister virtual file names (eg /dev/zero), and a + * function that retrieves a NULL-terminated list of such entries + * in a given directory. */ + + #ifndef __dj_include_libc_fsextdir_h_ + #define __dj_include_libc_fsextdir_h_ + + #ifdef __cplusplus + extern "C" { + #endif + + #ifndef __dj_ENFORCE_ANSI_FREESTANDING + #ifndef __STRICT_ANSI__ + #ifndef _POSIX_SOURCE + + void __fsext_register_entry(const char *_entry); + void __fsext_deregister_entry(const char *_entry); + + char **__fsext_entries(const char *_dir_name); + + #endif /* !_POSIX_SOURCE */ + #endif /* !__STRICT_ANSI__ */ + #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + + #ifdef __cplusplus + } + #endif + + #endif /* !__dj_include_libc_fsextdir_h_ */ *** /dev/null Mon Dec 25 17:51:37 2000 --- src/libc/fsext/fsextdir.c Mon Dec 25 17:38:44 2000 *************** *** 0 **** --- 1,25 ---- + /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ + + /* Written by Tim Van Holder. + * This file defines functions that allow fsext routines to + * register/deregister virtual file names (eg /dev/zero), and a + * function that retrieves a NULL-terminated list of such entries + * in a given directory. */ + + #include + + void + __fsext_register_entry (const char* d) + { + } + + void + __fsext_deregister_entry (const char* d) + { + } + + char** + __fsext_entries (const char* d) + { + return NULL; + } Index: src/libc/posix/dirent/closedir.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/dirent/closedir.c,v retrieving revision 1.2 diff -c -r1.2 closedir.c *** closedir.c 1998/11/15 13:48:38 1.2 --- closedir.c 2000/12/25 16:47:11 *************** *** 17,22 **** --- 17,29 ---- errno = e; else retval = -1; + if (dir->fsext_entries) + { + dir->fsext_entry = dir->fsext_entries; + while (*dir->fsext_entry != NULL) + free (*(dir->fsext_entry++)); + free (dir->fsext_entries); + } free(dir->name); free(dir); return retval; Index: src/libc/posix/dirent/dirstruc.h =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/dirent/dirstruc.h,v retrieving revision 1.3 diff -c -r1.3 dirstruc.h *** dirstruc.h 1996/09/11 23:23:52 1.3 --- dirstruc.h 2000/12/25 16:47:11 *************** *** 9,12 **** --- 9,15 ---- struct ffblk ff; struct dirent de; int need_fake_dot_dotdot; /* 0=no, 1=.., 2=. */ + int exists; + char **fsext_entries; + char **fsext_entry; }; Index: src/libc/posix/dirent/opendir.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/dirent/opendir.c,v retrieving revision 1.4 diff -c -r1.4 opendir.c *** opendir.c 2000/08/22 18:38:03 1.4 --- opendir.c 2000/12/25 16:47:11 *************** *** 5,10 **** --- 5,11 ---- /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include + #include #include #include #include *************** *** 59,70 **** char name_copy[FILENAME_MAX + 1]; if (!__solve_symlinks(name, name_copy)) ! return NULL; dir = (DIR *)malloc(sizeof(DIR)); if (dir == 0) return 0; dir->num_read = 0; dir->name = (char *)malloc(PATH_MAX); if (dir->name == 0) { --- 60,72 ---- char name_copy[FILENAME_MAX + 1]; if (!__solve_symlinks(name, name_copy)) ! return NULL; dir = (DIR *)malloc(sizeof(DIR)); if (dir == 0) return 0; dir->num_read = 0; + dir->exists = 1; dir->name = (char *)malloc(PATH_MAX); if (dir->name == 0) { *************** *** 79,90 **** /* Make absolute path */ _fixpath(name_copy, dir->name); ! /* Ensure that directory to be accessed exists */ if (access(dir->name, D_OK)) { ! free(dir->name); ! free(dir); ! return 0; } /* Strip trailing slashes, so we can append "/ *.*" */ --- 81,105 ---- /* Make absolute path */ _fixpath(name_copy, dir->name); ! dir->fsext_entries = __fsext_entries (dir->name); ! dir->fsext_entry = dir->fsext_entries; ! ! /* Ensure that directory to be accessed exists; only matters if there are ! * no entries faked by the fsext system. */ if (access(dir->name, D_OK)) { ! if (dir->fsext_entries == NULL) ! { ! free(dir->name); ! free(dir); ! return 0; ! } ! else ! { ! dir->exists = 0; ! dir->need_fake_dot_dotdot = 2; ! return dir; ! } } /* Strip trailing slashes, so we can append "/ *.*" */ Index: src/libc/posix/dirent/readdir.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/dirent/readdir.c,v retrieving revision 1.3 diff -c -r1.3 readdir.c *** readdir.c 1998/11/15 13:47:22 1.3 --- readdir.c 2000/12/25 16:47:13 *************** *** 17,35 **** int oerrno = errno; int mbsize; ! if (dir->need_fake_dot_dotdot) { /* Fake out . and .. on /; see opendir for comments */ ! dir->need_fake_dot_dotdot --; ! if (dir->need_fake_dot_dotdot) ! strcpy(dir->de.d_name, "."); ! else strcpy(dir->de.d_name, ".."); dir->de.d_namlen = strlen(dir->de.d_name); return &(dir->de); } ! if (dir->num_read) done = findnext(&dir->ff); else { --- 17,49 ---- int oerrno = errno; int mbsize; ! if (dir->num_read < dir->need_fake_dot_dotdot) { /* Fake out . and .. on /; see opendir for comments */ ! dir->num_read++; ! if (dir->num_read == dir->need_fake_dot_dotdot) strcpy(dir->de.d_name, ".."); + else + strcpy(dir->de.d_name, "."); dir->de.d_namlen = strlen(dir->de.d_name); return &(dir->de); } + + if (dir->fsext_entries != NULL && dir->fsext_entry != NULL) + { + strcpy (dir->de.d_name, *(dir->fsext_entry)); + dir->de.d_namlen = strlen (dir->de.d_name); + dir->fsext_entry++; + dir->num_read++; + if (*(dir->fsext_entry) == NULL) + dir->fsext_entry = NULL; + return &(dir->de); + } + + if (!dir->exists) + return NULL; ! if (dir->exists == 2) done = findnext(&dir->ff); else { *************** *** 39,44 **** --- 53,59 ---- if (dir->flags & __OPENDIR_FIND_LABEL) ff_flags |= FA_LABEL; done = findfirst(dir->name, &dir->ff, ff_flags); + dir->exists = 2; } if (done) { Index: src/libc/posix/dirent/rewinddi.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/dirent/rewinddi.c,v retrieving revision 1.2 diff -c -r1.2 rewinddi.c *** rewinddi.c 1998/11/15 13:48:38 1.2 --- rewinddi.c 2000/12/25 16:47:13 *************** *** 15,21 **** dir->ff.lfn_handle = 0; /* 0 means it's closed */ } - /* Recompute need_fake_dot_dotdot member. See comments in opendir.c. */ - __set_need_fake_dot_dotdot(dir); dir->num_read = 0; } --- 15,22 ---- dir->ff.lfn_handle = 0; /* 0 means it's closed */ } dir->num_read = 0; + if (dir->exists != 0) + dir->exists = 1; + dir->fsext_entry = dir->fsext_entries; }