home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / Dirent / dirent.doc < prev    next >
Text File  |  1993-07-04  |  7KB  |  163 lines

  1. Macintosh Directory Scanning Routines
  2.  
  3. By George T. Talbot
  4.  
  5. After programming on Sun workstations, I learned the usefulness of the "dirent" routines.
  6. These routines provide an easy, portable method of reading directory contents.  So, I
  7. implemented these routines on the Macintosh and tried to make them as close as possible
  8. to the UNIX routines.  Note that in this document I use the word "directory" instead of
  9. the word "folder".  Shoot me.
  10.  
  11. A couple of important notes before we begin:
  12.     Due to limitations in the Macintosh File System, all pathnames in this package are
  13.     limited to 255 characters (MAXPATHLEN).  If you want longer pathnames, you'll have
  14.     to break the pathnames up yourself.
  15.  
  16.     Any errors generated by these routines will be put in the global variable "dd_errno".
  17.  
  18. Here they are:
  19.  
  20. DIR    *opendir(char *dirname);
  21.  
  22.     This routine takes a Macintosh-style pathname and will open that directory and
  23.     make it ready for reading.  You may also pass in nil instead of a pointer to
  24.     a string to open the current working directory.
  25.     
  26.     If you've really got to use UNIX-style pathnames, you can set the variable
  27.     "dd_xform_seps" to true and "/" will be transformed to ":" by this routine.  Note
  28.     that if the individual directory names have "/" in them, that this routine will
  29.     not be able to open any path with that directory name in them while this variable
  30.     is true.  The default value of this variable is false.
  31.     
  32.     It is important to remember that the pathname, whatever separator is used, is a
  33.     Macintosh pathname and not a UNIX pathname.  This is important for relative pathnames.
  34.     
  35.     ".:", "..:" & "≈:" are supported if the pathname starts with
  36.     these strings.  ".:" means "relative to current directory" and "..:" & "≈:" mean
  37.     relative to the current directory's parent directory.
  38.     
  39.     This routine will return a pointer to a DIR structure:
  40.  
  41.         typedef    struct __dirdesc {
  42.             /*    PRIVATE FIELDS.  Use the fields & defines below PUBLIC */
  43.             ...
  44.         
  45.             /*    PUBLIC    */
  46.             long    dd_fd;            /* file descriptor (dirID) of this dir    */
  47.         
  48.         #define    dd_parent    ...        /* dirID of parent    */
  49.         #define    dd_bsize    ...        /* amount of entries read at a time (always 1) */
  50.         #define    dd_size        ...        /* amount of valid data in buffer (ignore) */
  51.         #define    dd_loc        ...        /* Don't remember what this field means    */
  52.         #define    dd_name        ...        /* Directory name (C string)    */
  53.         #define    dd_volume    ...        /* vRefNum where this is located    */
  54.         
  55.             long    dd_numents;        /* Number of files/directories in this directory    */
  56.         } DIR;
  57.  
  58.     I do have one significant departure from the UNIX way of doing things.  The field
  59.     "dd_fd" in UNIX will identify a particular folder, no matter what filesystem the
  60.     directory is in.  On the Mac, you'll require that field and dd_volume to identify
  61.     the directory.  Most programs won't have to look at those fields.
  62.  
  63.     The default separator is held in the variable "dd_separator".  This variable is a
  64.     pointer to a C string.  You could probably be compatible with A/UX by setting this
  65.     variable to "/" and dd_xform_seps to false, but I haven't tried this.
  66.  
  67. struct dirent *readdir(DIR *dirp);
  68.  
  69.     This routine reads the next directory entry in the directory (or the first one, if
  70.     opendir() has just been called).  This routine will return nil and set dd_errno to
  71.     noErr when the end of the directory is reached.  In case of error, it will also
  72.     return nil, but dd_errno will be set to some Mac error code.
  73.     
  74.     The structure this routine returns a pointer to looks like this:
  75.  
  76.         struct    dirent {
  77.             /* PRIVATE FIELDS.  Use fields after PUBLIC    */
  78.             ...
  79.             
  80.             /*    PUBLIC.    */
  81.             long            d_off;        /* index (to seekdir()) of this entry */    
  82.             long            d_fileno;    /* File number (dirID) of this entry    */
  83.         #define    d_parent    ...            /* File number (dirID) of parent    */
  84.         #define    d_reclen    ...            /* Size of this record    */
  85.         #define    d_namelen    ...            /*    Length of the name    */
  86.         #define    d_name        ...            /*    Name    */
  87.         #define    d_volume    ...            /* vRefNum where this is located    */
  88.         };
  89.  
  90.     The pointer you get to this structure is valid only while the directory is open.  When
  91.     the directory is closed with closedir(), this pointer goes away.
  92.  
  93. extern    int closedir(DIR *dirp);
  94.  
  95.     This routine closes a directory opened with opendir().  It will return -1 in case of
  96.     error and set dd_errno.  If you do get an error from this routine, get ready to crash
  97.     because the only errors that could happen are Memory Manager errors.
  98.  
  99. extern    void seekdir(DIR *dirp, long loc);
  100.  
  101.     In an open directory, this package indexes directory entries from 0 to the number
  102.     of entries in the directory-1 (0..n-1).  This function will seek to a specific
  103.     directory entry.  It's intended to be used before a call to readdir() or telldir().
  104.     
  105. extern    long telldir(DIR *dirp);
  106.  
  107.     This function will return the index of the next directory entry to be read from
  108.     the open directory specified by dirp, or -1 if the last entry has just been read.
  109.  
  110. extern    void rewinddir(DIR *dirp);
  111.  
  112.     This is equivalent to seekdir(dirp, 0).  It will seek to the first entry in the
  113.     open directory.
  114.  
  115. These routines are not part of a standard dirent package, but are VERY useful,
  116. nonetheless:
  117.  
  118. char    *getwd(char *path);
  119.  
  120.     This routine will get you a fully qualified pathname to the current working directory.
  121.     You'll pass in a pointer to a buffer of MAXPATHLEN characters.  If the routine is
  122.     successful, it will return the pointer to the buffer you passed in.  If it fails,
  123.     it will return nil and set dd_errno.
  124.  
  125. extern int    chdir(char *path);
  126.  
  127.     This routine will change the current working directory, given a path with the same
  128.     constraints as opendir().  It will return 0 on success, and will set dd_errno and
  129.     return -1 on failure.
  130.  
  131. extern char    *pathdir(DIR *dirp, char *path);
  132.  
  133.     Given a pointer to an open directory, this routine will generate a fully qualified
  134.     path name to that directory. You'll pass in a pointer to a buffer of MAXPATHLEN
  135.     characters.  If the routine is successful, it will return the pointer to the buffer
  136.     you passed in.  If it fails, it will return nil and set dd_errno.
  137.  
  138. That's about it.  This code may be used freely with the following caveats:
  139.  
  140.     1)    If you distribute source code with this code in it, distribute this documentation
  141.         file also.
  142.  
  143.     2)    If you include this code in a commercial product, send me a copy of the product
  144.         and make me a registered user.  If you feel that this is unfair, then send me
  145.         $10 U.S. and tell me why.  If you can't abide by this clause, then don't use this
  146.         code in your commercial product.
  147.  
  148.     3)    I'd like to see how far this thing goes, so send me a postcard if you use it and
  149.         find it useful.
  150.  
  151.     4)    If you find bugs in this code, let me know.  If you make any improvements, please
  152.         send me source so I can learn something.
  153.  
  154. This software was created with Think C 5.0.4 and tested on a Macintosh Centris 610 running
  155. System 7.  It should work with earlier Systems, but it probably won't work (and in fact
  156. will probably crash) without HFS.
  157.  
  158. George T. Talbot
  159. 24 Judy Ave.
  160. Franklinville, NJ  08322
  161.  
  162. <ugtalbot@mcs.drexel.edu>
  163.