home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / DIRPORT.HOW < prev    next >
Text File  |  1997-07-05  |  10KB  |  230 lines

  1. +++Date last modified: 05-Jul-1997
  2.  
  3. How to Use the Portable Directory Processing Functions in DIRPORT.H
  4. ===================================================================
  5.  
  6.  
  7. Background:
  8. -----------
  9.  
  10. All common PC operating systems (OS's) except Linux and FreeBSD are
  11. decendents of PC/MS-DOS and, as such, all use similar methods of processing
  12. directories. This is well established as a simple two-call sequence: 1) find
  13. the first file matching a given file specification; 2) find subsequent files
  14. matching the same specification. The file specification in either case may
  15. contain wildcards and/or directory path information as well as specific file
  16. attributes.
  17.  
  18. Where the various OS's and compilers diverge is in the details of this
  19. process. Different OS's, although descended from DOS, have different file
  20. types and different ways of masking which type of file(s) to process. Even
  21. within the same OS, different compilers have adopted different naming
  22. conventions for their (inherently non-portable) functions to call the
  23. underlying OS functionality.
  24.  
  25. At this point, it may be worthwhile to note that various Unix ports and
  26. clones often support the Posix-compliant directory processing functions,
  27. opendir(), readdir(), closedir(), seekdir(), and rewinddir(). A set of such
  28. functions is provided in SNIPPETS for those wishing to use these functions.
  29. The obvious advantage is portability. The disadvantage is that resulting
  30. programs will be larger and run more slowly when using these functions. The
  31. degree of impact will depend on the specifics of your application and
  32. environment, and may range from imperceptible to significant. The underlying
  33. cause is that the Posix functions must still be translated into the find
  34. first/find next calls supported by popular PC OS's.
  35.  
  36. The DIRPORT.H header file in SNIPPETS supports all major PC OS's (except for
  37. the Unix-ish ones) and compilers. Those already used to using the DOS
  38. interface find first/next calls will find it easy to use. The big problem is
  39. that, as support for more OS's and compilers has been added, DIRPORT.H has
  40. become somewhat unreadable, even to experienced programmers. This text is
  41. therefore a guide to using DIRPORT.H
  42.  
  43.  
  44. The basic concepts:
  45. -------------------
  46.  
  47. When finding the first file in a directory matching a given file
  48. specification, the OS needs to know three things:
  49.  
  50. 1.  The filename specification, which may contain wildcards and/or directory
  51.     information.
  52.  
  53. 2.  The type of file. This is typically specified as an integral data type
  54.     with bit-mapped file attributes.
  55.  
  56. 3.  A location where the resulting information will be stored in case the
  57.     specified file can be found.
  58.  
  59. The header file must therefore specify 4 items:
  60.  
  61. 1.  A function to call to find the first file.
  62.  
  63. 2.  A function to call to find subsequent files matching the specification.
  64.  
  65. 3.  Defined constants for specific file attributes.
  66.  
  67. 4.  A structure defining the data returned from the functions.
  68.  
  69. In addition, due to differences in PC OS's, one other function must be
  70. provided to close directory processing sessions.
  71.  
  72.  
  73. The implementation:
  74. -------------------
  75.  
  76. The structure used to process directory data is typedef'ed in DIRPORT.H as
  77. type DOSFileData. This is really all the user needs to know about it since
  78. all access to the elements of a DOSFileData structure is via macros defined
  79. in DIRPORT.H.
  80.  
  81. The function to find the first matching file is defined in DIRPORT,H as...
  82.  
  83.       FIND_FIRST(spec,attr,buf);
  84.  
  85. ...where "spec" is the filename specification, "attr" is the bit mapped file
  86. attribute mask, and "buf" is the address of the DOSFileData structure to
  87. receive information if a matching file can be found. FIND_FIRST returns 0 if
  88. successful, non-zero if no match could be found. If you're also using
  89. SNIPTYPE.H, you can therefore use the following:
  90.  
  91.       DOSFileData ff_info;
  92.       char fname[];
  93.       int AttributeMask;
  94.  
  95.  
  96.       if (Success_ == FIND_FIRST(fname, AttributeMask, &ff_info))
  97.       {
  98.             /* Do found it stuff here */
  99.       }
  100.       else
  101.       {
  102.             /* Do no match stuff here */
  103.       }
  104.  
  105. The attribute mask bits follow standard Microsoft practice and are defined in
  106. DIRPORT.H as:
  107.  
  108.   _A_NORMAL       All "normal" (i.e. none of the special types below) files.
  109.   _A_RDONLY       File cannot be written, only read.
  110.   _A_HIDDEN       File will not show up in a normal directory listing.
  111.   _A_SYSTEM       File is used by the system and cannot be moved.
  112.   _A_SUBDIR       The specification describes a subdirectory.
  113.   _A_VOLID        The file name is the volume ID (obsolescent).
  114.   _A_ARCH         File has been modified since last backed up.
  115.   _A_ANY          Any/all of the above.
  116.  
  117. The attribute masks are bitwise additive (see Note 1 below) and somewhat
  118. counter-intuitive in their operation. With the exception of the obsolescent
  119. _A_VOLID attribute, specifying any mask bit returns all files of that type
  120. matching the specification *PLUS* all "normal" files as well. If you
  121. therefore want to see only the subdirectories, you must use the _A_SUBDIR
  122. mask and then check each return file to see if it really is a subdirectory or
  123. simply another normal file.
  124.  
  125. As noted, specifying the _A_VOLID mask by itself will return only files with
  126. the volume ID attribute set. The volume ID was originally used to store the
  127. disk's "name", but that has been stored in sector zero since DOS 5 (see
  128. Note 2 below). The only use for the volume ID attribute in current versions
  129. of DOS is for reading pre-DOS 5 diskettes and in the specification of long
  130. file names under Windows 95.
  131.  
  132. Once you've found a match, you access the returned information using the
  133. following macros defined in DIRPORT.H:
  134.  
  135.  ff_name()  The name, minus path information, of the file found.
  136.  ff_size()  The size, in bytes, of the file found.
  137.  ff_attr()  The attributes of the file found.
  138.  ff_date()  The last modified date of the file found.
  139.  ff_yr()    The year specified in ff_date().
  140.  ff_mo()    The month specified in ff_date().
  141.  ff_day()   The day specified in ff_date().
  142.  ff_time()  The last modified time of the file found.
  143.  ff_hr()    The hours specified in ff_time().
  144.  ff_min()   The minutes specified in ff_time().
  145.  ff_tsec()  The seconds divided by two specified in ff_time().
  146.  
  147. Note that each is passed the address of the DOSFileData structure where
  148. FIND_FIRST() told the OS to store resulting information, e.g.
  149.  
  150.       file_size = ff_size(&ff_info);
  151.  
  152. As noted, the file name is the file's name within its own directory, i.e. no
  153. drive or path information is available. If you need drive and/or path infor-
  154. mation, you must have saved it when forming the filename specification, e.g.
  155.  
  156.       char *path;
  157.       char file_spec[FILENAME_MAX];
  158.       char full_name[FILENAME_MAX];
  159.       DOSFileData ff_info;
  160.  
  161.       sprintf(file_spec, "%s\\*.*", path);
  162.  
  163.       if (Success_ == FIND_FIRST(file_spec, _A_ANY, &ff_info))
  164.       {
  165.             sprintf(full_name, "%s\\%s", path, ff_name(&ff_info));
  166.       }
  167.  
  168. Once you've found the first matching file, you can find other files matching
  169. the specification (here we're assuming the original specification contained
  170. wildcards) by calling the FIND_NEXT(buf) function. It takes as its only
  171. argument, a pointer to the location of the DOSFileData structure and returns
  172. 0 if successful. Note that you can have several active directory processing
  173. sessions in a program, each using a different DOSFileData structure.
  174.  
  175. Putting together the examples given so far, you could process all the normal
  176. and read-only files plus subdirectories in the current directory as follows:
  177.  
  178.       DOSFileData ff_info;
  179.  
  180.       if (Success_ == FIND_FIRST("*.*", _A_RDONLY+_A_SUBDIR, &ff_info)) do
  181.       {
  182.             if (ff_attr(&ff_info) & _A_SUBDIR) /* Note use of bitwise AND! */
  183.             {
  184.                   /* Process subdirectories here /
  185.             }
  186.             else
  187.             {
  188.                   /* Process normal and read-only files here */
  189.             }
  190.       } while (Success_ == FIND_NEXT(&ff_info));
  191.       FIND_END(&ff_info);
  192.  
  193. Note that for compatibility with all supported OS's, when you're done with a
  194. particular directory processing session, you should call the FIND_END()
  195. function to clean up.
  196.  
  197. One final note... If using Win32 or OS/2, you must compile and link the
  198. DIRPORT.C file with your applications.
  199.  
  200. -----------------------------------------------------------------------------
  201.  
  202. Notes:
  203.  
  204. 1.  Attribute masks may be formed by adding or or'ing together specific
  205.     attributes, e.g.
  206.  
  207.       attr = _A_NORMAL + _A_RDONLY;       /* This is OK     */
  208.  
  209.       attr = _A_NORMAL | _A_RDONLY;       /* So is this     */
  210.  
  211.     However, when testing for specific attributes, you should always use the
  212.     & (bitwise AND) operator, e.g.
  213.  
  214.       if (ff_attr(&ff_info) & _A_RDONLY)
  215.  
  216.     *NEVER* use the && (logical AND) or == (equality) operators when testing
  217.     for file attributes!
  218.  
  219. 2.  Regarding volume ID's... Although the primary storage for the volume ID
  220.     has been in sector zero since the introduction of DOS 5, a single
  221.     directory entry with only the _A_VOLID bit set in the root directory is
  222.     still maintained for backwards compatibility. The file name of this
  223.     directory entry matches the volume ID as stored in disk sector 0.
  224.  
  225.  
  226. written by: Bob Stout
  227.             rbs@snippets.org
  228.             rbs@brokersys.com
  229.             1:106/2000.6
  230.