/************************************************************************ * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * * provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ************************************************************************/ /*+++* * title: readdir.h * abstract: basic directory handling. * author: T.R.Hageman, Groningen, The Netherlands. * created: January 1991, merged from existing sources. * modified: this obsoletes {atari,msdos}dir.inc * 23-Jul-91, add MAC types (implementation in mac.c) * description: * This declares the basic directory handling functions opendir, * readdir, closedir and the higher-level scandir and friends. * * If the compile-time flag READDIR_IMPLEMENTATION is defined, * a limited implementation (or emulation) of these opendir, readdir, * closedir is generated if your system does not support this -- if * your UNIX has BSD-style directory (long names) be sure to define * BSD_DIR so that the library readdir routines are used. * This is done this peculiar way since we need these both in JOVE * (from scandir.c) and in recover, in a slightly different version * for either, and I wanted to keep the system-dependencies localized. * * BUGS: * some systems do have readdir support but use different or * additional header files. * - MAC and VMS implementations are in "mac.c" and "vms.c", respectively. *---*/ #ifndef _READDIR_H_ #define _READDIR_H_ #ifndef TUNED # include "tune.h" #endif #ifdef READDIR_IMPLEMENTATION RCS_H(readdir, "$Id: readdir.h,v 14.30.0.6 1993/10/28 00:54:49 tom Exp tom $") #endif /* Define types `DIR' and `struct dirent' for systems that don't have'em. */ #if _I_DIRENT # include # define DIRSIZE(entry) (strlen((entry)->d_name)) # define BSD_DIR #else # define dirent direct # if unix # ifdef SYSNDIR # include # define BSD_DIR # else # ifndef SYSDIR # ifdef SYSV # include # define BSD_DIR # else # define SYSDIR /* Provide default. */ # endif # endif # ifdef SYSDIR # include # ifndef V7 # ifndef MINIX # define BSD_DIR # endif # endif # endif /* SYSDIR */ # endif /* SYSNDIR */ # ifdef BSD_DIR # define DIRSIZE(entry) ((entry)->d_namlen) # else # define DIRSIZE(entry) ((entry)->d_name[DIRSIZ-1] ? DIRSIZ : \ strlen((entry)->d_name)) # ifdef NOT_JOVE /* it is assumed that is already included */ # define DIR FILE # else # ifndef _IO_H_ # include "io.h" # endif # define DIR File # endif # endif # else /* !unix */ # ifdef DOS # define DIRSIZ 14 /* 8 + 1 + 3 + 1 rounded up to word-boundary */ # endif # ifdef MAC # define DIRSIZ FILESIZE # endif # if vms # define DIRSIZ FILESIZE # endif struct direct { char d_name[DIRSIZ]; }; # define DIRSIZE(entry) (strlen((entry)->d_name)) # endif /* unix */ /* Hide differences between Atari and MSDOS */ # ifdef DOS # ifdef ATARIST # include /* should define DTA */ # ifdef __GNUC__ # define DTA struct _dta # endif # endif # ifdef MSDOS # include # ifdef __TURBOC__ # include # define DTA struct ffblk # else /* MSC */ # define DTA struct find_t # endif # endif typedef struct { DTA d_dta; # ifdef ATARIST DTA *d_orgdta; # endif } DIR; # endif /* DOS */ # ifdef MAC typedef struct { int d_vol_id; long d_dir_id; int d_index; } DIR; # endif /* MAC */ # if vms typedef struct { int d_context; char d_vms_dirname[FILESIZE]; int d_baselen; struct { unsigned short length; char body[FILESIZE]; } d_next_entry; } DIR; # endif /* vms */ #endif /* _I_DIRENT */ /* function prototypes. */ #ifndef BSD_DIR # ifndef NO_PROCDECL extern DIR *opendir __(( const char *_(dir) )); extern struct dirent *readdir __(( DIR *_(dp) )); extern void closedir __(( DIR *_(dp) )); # endif #endif #ifndef NOT_JOVE # ifdef CHDIR # ifndef TINY extern int ask_dir_only; # endif # endif #else # define ask_dir_only (-1) #endif /* This is requested from scandir.c and recover.c */ #ifdef READDIR_IMPLEMENTATION # if !_I_DIRENT # ifndef S_ISDIR /* not yet loaded? */ # ifndef S_IFDIR # if _I_SYS_STAT - -1 # include # else # if _I_STAT # include # endif # endif # endif # ifndef S_ISDIR # define S_ISDIR(m) (((m)&S_IFMT)==S_IFDIR) # endif # endif # if unix # ifndef BSD_DIR # # ifdef NOT_JOVE # define DIR_OPEN(dname) fopen(dname, "rb") # define DIR_STAT(d,st) fstat(fileno(d), st) # define DIR_CLOSE(d) fclose(d) # define DIR_READ(d,b,s) (fread(b, 1, s, d) - s) # else # define DIR_OPEN(dname) f_open(dname, F_READ|F_BINARY, iobuff, BLKSIZ) # define DIR_STAT(d,st) fstat((d)->f_fd, st) # define DIR_CLOSE(d) f_close(d) # define DIR_READ(d,b,s) fgetnchar((char *)(b), s, d) # endif /* At most one DIR can be active simultaneously, but that is all we need. */ DIR * opendir(dir) const char *dir; { register DIR *dp; struct stat stbuf; if (dp = DIR_OPEN(dir)) { if (DIR_STAT(dp, &stbuf) < 0 || !S_ISDIR(stbuf.st_mode)) { closedir(dp); dp = NULL; /* this isn't a directory! */ } } return dp; } void closedir(dp) DIR *dp; { DIR_CLOSE(dp); } struct direct * readdir(dp) register DIR *dp; { static struct direct dir; do if (DIR_READ(dp, &dir, sizeof dir) != 0) return NULL; while (dir.d_ino == 0); return &dir; } # undef DIR_OPEN # undef DIR_STAT # undef DIR_CLOSE # undef DIR_READ # endif /* !BSD_DIR */ # endif /* unix */ # ifdef DOS # ifndef _IO_H # include "io.h" /* for FIX_FILENAME */ # endif /* More disguise. */ # ifdef ATARIST # ifdef __GNUC__ # define d_attrib dta_attribute # define d_fname dta_name # define FA_READONLY FA_RDONLY # define FA_SUBDIR FA_DIR # define FA_ARCHIVE FA_CHANGED # endif # define DIR_FIRST(name,mode,dp) ((dp)->d_orgdta = Fgetdta(), \ Fsetdta(&(dp)->d_dta), \ (int) Fsfirst(name, mode)) # define DIR_NEXT(dp) Fsnext() # define DIR_CLOSE(dp) Fsetdta((dp)->d_orgdta) # define FA_ALL (FA_READONLY|FA_HIDDEN|FA_SYSTEM|FA_SUBDIR|FA_ARCHIVE) # endif # ifdef MSDOS # ifdef __TURBOC__ # define d_fname ff_name # define d_attrib ff_attrib # define DIR_FIRST(n,m,dp) findfirst(n, &(dp)->d_dta, m) # define DIR_NEXT(dp) findnext(&(dp)->d_dta) # define DIR_CLOSE(dp) # define FA_ALL (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC|FA_ARCH) # define FA_SUBDIR FA_DIREC # else /* MSC */ # define d_fname name # define d_attrib attrib # define DIR_FIRST(n,m,dp) _dos_findfirst(n,m,&(dp)->d_dta) # define DIR_NEXT(dp) _dos_findnext(&(dp)->d_dta) # define DIR_CLOSE(dp) # define FA_ALL (_A_NORMAL|_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_SUBDIR|_A_ARCH) # define FA_SUBDIR _A_SUBDIR # endif # endif /* At most one DIR can be active simultaneously, but that is all we need. */ DIR * opendir(dir) const char *dir; { static DIR theDIR; register DIR *dp = &theDIR; char dirpath[FILESIZE]; struct stat stbuf; make_filename(dirpath, dir, "*.*"); if (DIR_FIRST(dirpath, FA_ALL, dp) != 0) { if (stat(dir, &stbuf) < 0 || !S_ISDIR(stbuf.st_mode)) { closedir(dp); return NULL; } dp->d_dta.d_fname[0] = '\0'; /* to flag the end */ } return dp; } /* opendir */ void closedir(dp) register DIR *dp; { DIR_CLOSE(dp); } struct direct * readdir(dp) register DIR *dp; { static struct direct dir; if (dp->d_dta.d_fname[0] == '\0') return NULL; # ifndef NOT_JOVE # ifdef CHDIR # ifndef TINY /* Cheat -- deliver only directories if so requested; This is much more efficient than delivering all filenames and stat()ing each of them. */ if (ask_dir_only >= 0) while (!(dp->d_dta.d_attrib & FA_SUBDIR)) if (DIR_NEXT(dp) != 0) return NULL; # endif # endif # endif strcpy(dir.d_name, dp->d_dta.d_fname); FIX_FILENAME(dir.d_name); if (DIR_NEXT(dp) != 0) dp->d_dta.d_fname[0] = '\0'; /* to flag the end */ return &dir; } # undef DIR_FIRST # undef DIR_NEXT # undef DIR_CLOSE # undef FA_ALL # undef d_fname # endif /* DOS */ # ifdef MAC # ifdef NOT_JOVE # include "mac.c" /* most of which is excluded. */ # endif # endif # if vms # ifdef NOT_JOVE # include "vms.c" /* most of which is excluded. */ # endif # endif # endif /* _I_DIRENT */ #endif /* READDIR_IMPLEMENTATION */ /* scandir.c */ #ifndef NOT_JOVE # ifdef F_COMPLETION /* this is to avoid conflict with prototype in on some systems. */ # define scandir Jscandir # define freedir Jfreedir #ifndef NO_PROCDECL extern int scandir __(( const char *_(dir), char ***_(nmptr), int (*_(qualify))(const char *_(name)), int (*_(sorter))(const char **_(a), const char **_(b)) )); extern void freedir __(( char ***_(nmptr), int _(nent) )); #endif /* NO_PROCDECL */ extern int alphacomp __(( const char **_(a), const char **_(b) )); # endif #endif #endif /* _READDIR_H_ */ /*====================================================================== * $Log: readdir.h,v $ * Revision 14.30.0.6 1993/10/28 00:54:49 tom * (DOS) readdir: replace strlwr() with FIX_FILENAME(). * * Revision 14.30 1993/01/26 18:43:05 tom * cleanup whitespace. * * Revision 14.28 1992/10/23 17:15:58 tom * convert to "port{ansi,defs}.h" conventions; improve Posix compatibility. * * Revision 14.27 1992/09/21 23:54:20 tom * add missing #endif (how did I miss it???); remove empty `#' directives. * * Revision 14.26 1992/08/26 23:56:47 tom * some portability improvements (I hope:-); add RCS directives. * */