home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / OWLSCR / OS2DIR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-29  |  20.0 KB  |  763 lines

  1. /*
  2.     os2dir.c -mla
  3.  
  4.     % OS/2-specific file and directory handling functions.
  5.  
  6.     OWL-PC 1.2
  7.     Copyright (c) 1990 by Oakland Group, Inc.
  8.     ALL RIGHTS RESERVED.
  9.  
  10.     Revision History:
  11.     -----------------
  12.      9/15/90 ted    Fixed srchcnt and hdir initialization for DosFindFirst.
  13.      9/15/90 ted    Fixed case in odir_Split when spec is NULL.
  14.     10/20/90 mla    changed ostrlower to os2dir_StripCase & added (char) cast
  15.     10/28/90 mla    updated, preened
  16. */
  17. /* -------------------------------------------------------------------------- */
  18. #include <ctype.h>
  19. #include <time.h>
  20.  
  21. #include "os2priv.h"
  22. #include "oaktag.h"
  23. #include "oaktime.h"
  24. #include "oakdir.h"
  25.  
  26. /*  mask to ignore bit not used in the masks for odir_Open  */
  27. #define OFILE_MASK        0x07
  28.  
  29. /*  DOS path separator character  */
  30. #define OFILE_SEPCHAR    '\\'
  31.  
  32. /*  os/2 file type filter function  */
  33. OSTATIC boolean typemask(byte type, byte mask);
  34.  
  35. /* OS/2 dependent directory info here (what odir_type points to) */
  36. typedef struct _os2dir {
  37.     boolean        first;
  38.     char        path[OFILE_PATHLEN];
  39.     FILEFINDBUF    file_buf;
  40.     HDIR        hdir;
  41.     USHORT        srchcnt;
  42.     byte        file_type;
  43. } os2dir_struct;
  44. /* -------------------------------------------------------------------------- */
  45.  
  46. odir_type os2dir_Open(char *user_spec, byte file_type)
  47. /*
  48.     This routine opens an oakland directory stream and returns a handle to it.
  49.     The handle is then used in calls to odir_Read, and odir_Close.
  50.     If the stream cannot be opened for any reason NULL is returned.
  51.  
  52.     The first parameter is a string which should specify a path to the 
  53.     directory and a mask to use to filter the filenames in the directory.
  54.     If the first paramater is specifies only a path (no file mask), the 
  55.     indicated directory is used and the filenames are not filtered.    If the 
  56.     first paramater is NULL or "", the current directory is used and 
  57.     the filenames are not filtered.  
  58.  
  59.     The second parameter is a mask which is used to filter the directory 
  60.     entries by type.  Defined masks are:  
  61.         OFILE_ALL     - does no type filtering.  Everything available from
  62.                       the opering system.
  63.         OFILE_DIRS    - Returns subdirectories within the specified directory.
  64.         OFILE_FILES - Returns files in the specified directory.
  65.     The masks can be used alone or in combination with each other by bitwise
  66.     or'ing the masks together.  If OFILE_ALL is used in conjuction with other 
  67.     masks, it has the same effect as if used alone.
  68. */
  69. {
  70.     os2dir_struct    *odirp;
  71.     char            *internal_spec, dummy_name[OFILE_NAMELEN];
  72.     USHORT            os2type;
  73.  
  74.     /*  specify os2type such that os/2 will filter file types for us  */
  75.     if (file_type & OFILE_ALL) {
  76.         os2type = FILE_NORMAL | FILE_READONLY | FILE_HIDDEN 
  77.             | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
  78.     }
  79.     else if ((file_type & (OFILE_DIRS | OFILE_FILES)) == 0) {
  80.  
  81.         return(NULL);
  82.     }
  83.  
  84.     os2type = 0;
  85.     if (file_type & OFILE_DIRS) {
  86.         os2type |= FILE_DIRECTORY;
  87.     }
  88.     if (file_type & OFILE_FILES) {
  89.         os2type |= FILE_NORMAL | FILE_READONLY | FILE_SYSTEM | FILE_ARCHIVED;
  90.     }
  91.  
  92.     /*  allocate the odir struct  */
  93.     if ((odirp = (os2dir_struct *) omalloc(ID_ODIR, sizeof(os2dir_struct))) == NULL) {
  94.         return (NULL);
  95.     }
  96.  
  97.     /*  adjust path to include a wildcard for filenames  */
  98.     if (user_spec == NULL || *user_spec == '\0') {
  99.         if ((internal_spec = (char *) omalloc(OA_NOTAG, 4)) == NULL) {
  100.             ofree(ID_ODIR, odirp);
  101.             odirp = NULL;
  102.             return(NULL);
  103.         }
  104.         strcpy(internal_spec, OFILE_WILDCARD);
  105.     }
  106.     else {
  107.         if (user_spec[strlen(user_spec) - 1] == OFILE_SEPCHAR
  108.                 || user_spec[strlen(user_spec) - 1] == ':') {
  109.             /*  user_spec is just a path (no file mask)  */
  110.             if ((internal_spec = (char *) omalloc(OA_NOTAG, strlen(user_spec) 
  111.                     + strlen(OFILE_WILDCARD) + 1)) == NULL) {
  112.                 ofree(ID_ODIR, odirp);
  113.                 odirp = NULL;
  114.                 return(NULL);
  115.             }
  116.             strcpy(internal_spec, user_spec);
  117.             strcat(internal_spec, OFILE_WILDCARD);
  118.         }
  119.         else {
  120.             if ((internal_spec = (char *) omalloc(OA_NOTAG, strlen(user_spec)))
  121.                     == NULL) {
  122.                 ofree(ID_ODIR, odirp);
  123.                 odirp = NULL;
  124.                 return(NULL);
  125.             }
  126.             strcpy(internal_spec, user_spec);
  127.         }
  128.     }
  129.                 
  130.     odirp->srchcnt = 1;
  131.     if (os2data->dosbox) {
  132.          odirp->hdir = HDIR_SYSTEM;
  133.     }
  134.     else odirp->hdir = HDIR_CREATE;
  135.  
  136.     /* If no more matches */
  137.     if (DosFindFirst(internal_spec, &odirp->hdir, os2type, &odirp->file_buf, 
  138.             sizeof(FILEFINDBUF), &odirp->srchcnt, 0L) != 0) {
  139.  
  140.         ofree(ID_ODIR, odirp);
  141.         odirp = NULL;
  142.     }
  143.     ofree(OA_NOTAG, internal_spec);
  144.  
  145.     if (odirp == NULL) {
  146.         return(NULL);
  147.     }
  148.     odirp->first = TRUE;
  149.  
  150.     /*  pass requested attrs down so read can set ofile attrs correctly  */
  151.     odirp->file_type = file_type;
  152.  
  153.     /*  pass the path down so it can be appended to the filenames when output  */
  154.     os2dir_Split(user_spec, odirp->path, sizeof(odirp->path), dummy_name, sizeof(dummy_name));
  155.  
  156.     return((odir_type) odirp);
  157. }
  158. /* -------------------------------------------------------------------------- */
  159.  
  160. boolean os2dir_Read(odir_type odirpa, ofile_struct *file_info)
  161. /*
  162.     This routine reads the next entry from an oakland directory    stream.
  163.     If an entry is found to return, odir_Read returns TRUE.  If there
  164.     are no more entries in the stream, it returns FALSE.
  165.  
  166.     The first parameter is the directory stream from which to fetch an entry.
  167.  
  168.     The second parameter is a pointer to an ofile_struct where the information
  169.     about the entry will be stored.  Once the information has been put into 
  170.     the ofile_struct, the following macros may be used to access it:
  171.         ofile_GetType()  - returns the type of the file:  OFILE_ALL if it was
  172.                            specified in the call to odir_Open for this stream,
  173.                            OFILE_FILES for files, and OFILE_DIRS for dirs.
  174.         ofile_GetTime()  - returns an ansi struct tm with the date and time 
  175.                            the file was last modified.
  176.         ofile_GetSize()  - returns the size of the file in bytes.
  177.         ofile_GetSpec()  - returns the spec for the file including a path
  178.                            starting where the spec given to odir_Open started.
  179.     They each take a single parameter:  the ofile_struct of the entry of 
  180.     interest.  (Note:  NOT a pointer to the ofile_struct)
  181. */
  182. {
  183.     os2dir_struct    *odirp;
  184.     boolean            foundone;
  185.  
  186.     odirp = (os2dir_struct *) odirpa;
  187.  
  188.     if (odirp == NULL) {
  189.         return(FALSE);
  190.     }
  191.  
  192.     if (odirp->first) {            /* If first use the first buf full */
  193.         odirp->first = FALSE;
  194.         foundone = TRUE;
  195.     }
  196.     else {                        /* Otherwise get a new buf full */
  197.         /* If no more matches  */
  198.         odirp->srchcnt = 1;
  199.         if (DosFindNext(odirp->hdir, &odirp->file_buf, sizeof(FILEFINDBUF), 
  200.                 &odirp->srchcnt) != 0) { 
  201.             foundone = FALSE;
  202.         }
  203.         else {
  204.             foundone = TRUE;
  205.         }
  206.     }
  207.  
  208.     if (foundone) {
  209.         /* Copy from OS/2 buf structure into OS-independent file_info structure */
  210.  
  211.         /*  files attributes  */
  212.         if (odirp->file_type & OFILE_ALL) {
  213.             file_info->type = OFILE_ALL;
  214.         }
  215.         else {
  216.             switch (OFILE_MASK & odirp->file_type) {
  217.             case OFILE_DIRS:
  218.             case OFILE_FILES:
  219.                 file_info->type = odirp->file_type;
  220.                 break;
  221.             case OFILE_DIRS | OFILE_FILES:
  222.                 if (odirp->file_buf.attrFile & FILE_DIRECTORY) {
  223.                     file_info->type = OFILE_DIRS;
  224.                 }
  225.                 else {
  226.                     file_info->type = OFILE_FILES;
  227.                 }
  228.                 break;
  229.             }
  230.         }
  231.  
  232.         /*  time of last write  */
  233.         file_info->time.tm_hour = odirp->file_buf.ftimeLastWrite.hours;
  234.         file_info->time.tm_min  = odirp->file_buf.ftimeLastWrite.minutes;
  235.         file_info->time.tm_sec  = odirp->file_buf.ftimeLastWrite.twosecs * 2;
  236.  
  237.         /*  date of last write  */
  238.         file_info->time.tm_year = odirp->file_buf.fdateLastWrite.year;
  239.         file_info->time.tm_mon  = odirp->file_buf.fdateLastWrite.month;
  240.         file_info->time.tm_mday = odirp->file_buf.fdateLastWrite.day;
  241.  
  242.         /*  calculate weekday, yearday, and dst values  */
  243.         tm_Adjust(&file_info->time);
  244.  
  245.         file_info->size = odirp->file_buf.cbFileAlloc;     /*  size of file  */
  246.  
  247.         os2dir_Join(file_info->spec, sizeof(file_info->spec), odirp->path, 
  248.             odirp->file_buf.achName);                    /*  name of file  */
  249.         os2dir_StripCase(file_info->spec);
  250.     }
  251.  
  252.     return(foundone);
  253. }
  254. /* -------------------------------------------------------------------------- */
  255.  
  256. void os2dir_Close(odir_type odirpa)
  257. /*
  258.     This routine closes an oakland directory stream and frees all resources
  259.     it used.
  260.  
  261.     It's single parameter is the hanlde to the stream to close.
  262. */
  263. {
  264.     os2dir_struct    *odirp;
  265.  
  266.     odirp = (os2dir_struct *) odirpa;
  267.  
  268.     if (odirp != NULL) {
  269.         DosFindClose(odirp->hdir);
  270.         ofree(ID_ODIR, odirp);
  271.     }
  272.     return;
  273. }
  274.  
  275. /* -------------------------------------------------------------------------- */
  276.  
  277. boolean    os2file_IsValid(char *name, boolean wildok)
  278. /*
  279.     determines if a filename is valid under the operating system.
  280. */
  281. {
  282.     char    goodchrs[13];
  283.     int        i, dots, dot = -1;
  284.  
  285.     if (wildok == TRUE) {
  286.         strcpy(goodchrs, "@!-{}_`^~.*?");
  287.     }
  288.     else {
  289.         strcpy(goodchrs, "@!-{}_`^~.");
  290.     }
  291.  
  292.     for (dots = i = 0; name[i] != '\0'; i++) {
  293.         if (!(name[i] > 64 && name[i] < 91)            /*  [a-z]  */
  294.                 && !(name[i] > 96 && name[i] < 123)    /*  [A-Z]  */
  295.                 && !(name[i] > 47 && name[i] < 58)    /*  [0-9]  */
  296.                 && !(name[i] > 34 && name[i] < 42)    /*  [#$%&'()]  */
  297.                 && !strchr(goodchrs, name[i])) {
  298.  
  299.             return(FALSE);
  300.         }
  301.  
  302.         /*  only one dot allowed and not in the first position  */
  303.         if (name[i] == '.') {
  304.             if (++dots > 1 || i == 0) {
  305.  
  306.                 return(FALSE);
  307.             }
  308.  
  309.             dot = i;
  310.         }
  311.     }
  312.  
  313.     if (dot == -1) {  /*  there was no dot  */
  314.         if (i > 8) {
  315.  
  316.             return(FALSE);
  317.         }
  318.     }
  319.     else if (i - dot > 4 || dot > 8) {
  320.  
  321.         return(FALSE);
  322.     }
  323.  
  324.     return(TRUE);
  325. }
  326. /* -------------------------------------------------------------------------- */
  327.  
  328. boolean    os2dir_IsValid(char *dir)
  329. /*
  330.     determines if a directory is valid under the operating system.
  331. */
  332. {
  333.     char    *s, *start;
  334.     int        i;
  335.  
  336.     /*  empty string is valid (current dir)  */
  337.     if (*dir == '\0') {
  338.         return(TRUE);
  339.     }
  340.  
  341.     s = dir;
  342.  
  343. /*  drive  */
  344.     if (isalpha(*s) && *(s + 1) == ':') {
  345.         s += 2;
  346.     }
  347.  
  348. /*   main loop  */
  349.     while (*s != '\0') {
  350.  
  351.     /*  slash  */
  352.         if (*s == OFILE_SEPCHAR) {
  353.             s++;
  354.             
  355.             /*  skip all adjacent slashs  */
  356.             while (*s == OFILE_SEPCHAR) {
  357.                 s++;
  358.             }
  359.         }
  360.  
  361.     /*  directories  */
  362.         start = s;
  363.  
  364.         for (i = 0; *s != '\0' && *s != '.' && *s != OFILE_SEPCHAR; s++) {
  365.  
  366.             /*  is this a legal directory char  */
  367.             if ((*s > 64 && *s < 91)            /*  [a-z]  */
  368.                     || (*s > 96 && *s < 123)    /*  [A-Z]  */
  369.                     || (*s > 47 && *s < 58)    /*  [0-9]  */
  370.                     || (*s > 34 && *s < 42)    /*  [#$%&'()]  */
  371.                     || strchr("@!-{}_`^~", *s)) {
  372.         
  373.                 i++;    
  374.                 if (i == 8) {
  375.                     /*  skip till '.', OFILE_SEPCHAR or '\0'  */
  376.                     for (s++; *s != '.' && *s != '\0' && *s != OFILE_SEPCHAR; s++)
  377.                         ;
  378.                     break;
  379.                 }
  380.             }
  381.             else {
  382.                 return(FALSE);
  383.             }
  384.         }
  385.         
  386.         /*  now where at either a '.', OFILE_SEPCHAR or '\0' in the source string  */
  387.  
  388. /*  dot  */
  389.         /*  '..' = parent directory case  */        
  390.         if (*s == '.' && *(s + 1) == '.' 
  391.                 && (*(s + 2) == OFILE_SEPCHAR || *(s + 2) == '\0')) {
  392.             s += 2;
  393.             continue;
  394.         }
  395.  
  396.         /*  '.' = current directory case  */
  397.         if (*s == '.' && (*(s + 1) == OFILE_SEPCHAR || *(s + 1) == '\0')) {
  398.             s++;
  399.             continue;
  400.         }
  401.  
  402.         if (*s == '.') {
  403.  
  404.             /*  if the dot is the first char, this spec is invalid  */
  405.             if (s == start) {
  406.                 return(FALSE);
  407.             }
  408.             s++;
  409.  
  410.             /*  dot not allowed in last position  */
  411.             if (*s == OFILE_SEPCHAR || *s == '\0') {
  412.                 return(FALSE);
  413.             }
  414.  
  415. /*  extention  */
  416.             for (i = 0; *s != '\0' && *s != OFILE_SEPCHAR; s++) {
  417.  
  418.                 /*  is this a legal directory char  */
  419.                 if ((*s > 64 && *s < 91)            /*  [a-z]  */
  420.                         || (*s > 96 && *s < 123)    /*  [A-Z]  */
  421.                         || (*s > 47 && *s < 58)    /*  [0-9]  */
  422.                         || (*s > 34 && *s < 42)    /*  [#$%&'()]  */
  423.                         || strchr("@!-{}_`^~", *s)) {
  424.  
  425.                     i++;
  426.                     if (i > 3) {
  427.                         return(FALSE);
  428.                     }
  429.                 }
  430.                 else {
  431.                     return(FALSE);
  432.                 }
  433.             }
  434.         }
  435.     }
  436.  
  437.     return(TRUE);
  438. }
  439. /* -------------------------------------------------------------------------- */
  440.  
  441. boolean    os2dir_MakePath(char *dirbuf, int buflen, char *dir)
  442. /*
  443.     if the supplied string is not empty, we modify it to indicate a path
  444. */
  445. {
  446.     int dirlen;
  447.  
  448.     if (*dir == '\0') {
  449.         *dirbuf = '\0';
  450.  
  451.         return(TRUE);
  452.     }
  453.  
  454.     dirlen = strlen(dir);
  455.  
  456.      if (dir[dirlen - 1] == OFILE_SEPCHAR) {
  457.         if (buflen > dirlen) {
  458.             if (dirbuf != dir) {
  459.                 strcpy(dirbuf, dir);
  460.             }
  461.  
  462.             return(TRUE);
  463.         }
  464.     }
  465.     else {
  466.         if (buflen > dirlen + 1) {
  467.             if (dirbuf != dir) {
  468.                 strcpy(dirbuf, dir);
  469.             }
  470.             dirbuf[dirlen] = OFILE_SEPCHAR;
  471.             dirbuf[dirlen + 1] = '\0';
  472.  
  473.             return(TRUE);
  474.         }
  475.     }
  476.     return(FALSE);
  477. }
  478. /* -------------------------------------------------------------------------- */
  479.  
  480. boolean os2dir_Ascend(char *newpath, int maxnewpath, char *oldpath)
  481. /*
  482.     This routine forms a string representing the path to the parent directory 
  483.     of the path represented by the given string.  It does no checking with
  484.     the directory system to verify either of the paths are valid; It simply
  485.     minipulates the strings.
  486.  
  487.     The first parameter points to the location where the result string should
  488.     be stored.
  489.  
  490.     The second parameter is the size of the available space pointer to by 
  491.     the first parameter.
  492.  
  493.     The third parameter is the supplied string representing the starting path.
  494.     The path must end with the separator character for paths of the operating
  495.     system and be null terminated.  Under OS2 the is '\\'.
  496.  
  497.     It returns TRUE if successful, FALSE otherwise.
  498. */
  499. {
  500.     int    i;        /*  the new path length  */
  501.  
  502.     os2dir_MakePath(newpath, maxnewpath, oldpath);
  503.     i = strlen(newpath);
  504.  
  505.     /*  can't ascend above root directory  */
  506.     if (i == 1 && newpath[0] == OFILE_SEPCHAR) {
  507.  
  508.         return(FALSE);
  509.     }
  510.  
  511.     /*  if there isn't a subdir availiable to chop, append "../" to ascend  */
  512.     if (i == 0 || (newpath[i - 2] == '.' && newpath[i - 3] == '.')) {
  513.         if (i + 3 <= maxnewpath) {
  514.  
  515.             /*  strcat "../"  */
  516.             newpath[i] = '.';
  517.             newpath[i + 1] = '.';
  518.             newpath[i + 2] = OFILE_SEPCHAR;
  519.             newpath[i + 3] = '\0';
  520.  
  521.             return(TRUE);
  522.         }
  523.         return(FALSE);
  524.     }
  525.  
  526.     /*  chop last subdir  */
  527.     for (i -= 2; newpath[i] != OFILE_SEPCHAR && newpath[i] != ':' && i > 0; i--)
  528.         ;
  529.     if (newpath[i] == OFILE_SEPCHAR || newpath[i] == ':') {
  530.         newpath[i + 1] = '\0';
  531.     }
  532.     else {
  533.         *newpath = '\0';
  534.     }
  535.     return(TRUE);
  536. }
  537. /* -------------------------------------------------------------------------- */
  538.  
  539. boolean os2dir_Descend(char *newpath, int maxnewpath, char *oldpath, char *subdir)
  540. /*
  541.     This routine forms a string representing the path to a child directory 
  542.     of the path represented by the given string.  It does no checking with
  543.     the directory system to verify either of the paths are valid; It simply
  544.     minipulates the strings.
  545.  
  546.     The first parameter points to the location where the result string should
  547.     be stored.
  548.  
  549.     The second parameter is the size of the available space pointer to by 
  550.     the first parameter.
  551.  
  552.     The third parameter is the supplied string representing the starting path.
  553.     The path must end with the separator character for paths of the operating
  554.     system and be null terminated.  Under Dos the is '\\'.
  555.  
  556.     The fourth parameter is a string indicating into which subdirectory
  557.     to descend
  558.  
  559.     It returns TRUE if successful, FALSE otherwise.
  560. */
  561. {
  562.     int    oldpathlen, subdirlen;
  563.  
  564.     oldpathlen = strlen(oldpath);
  565.     subdirlen = strlen(subdir);
  566.  
  567.     if (oldpathlen + subdirlen < maxnewpath) {
  568.         if (newpath != oldpath) {
  569.             strcpy(newpath, oldpath);
  570.         }
  571.         newpath += oldpathlen;
  572.         strcpy(newpath, subdir);
  573.         newpath += subdirlen;
  574.         if (*(newpath - 1) != OFILE_SEPCHAR) {
  575.             *newpath = OFILE_SEPCHAR;
  576.             newpath++;
  577.         }
  578.         *newpath = '\0';
  579.         return(TRUE);
  580.     }
  581.     return(FALSE);
  582. }
  583. /* -------------------------------------------------------------------------- */
  584.  
  585. boolean os2dir_Split(char *spec, char *path, int maxpath, char *name, int maxname)
  586. /*
  587.     This routine separates a string representing a file spec into a string 
  588.     representing the path of the spec and a string representing the filename
  589.     of the spec.  If supplied with only a filename, it sets the path to "".
  590.     If supplied with only a path (terminated with the operating systems path
  591.     separator character), it sets the filename to "".  If supplied with "", it 
  592.     sets both the path and name to "".   It does no checking with the directory 
  593.     system to verify either the path or the filename is    valid; It simply 
  594.     manipulates the strings.
  595.  
  596.     The first parameter is the supplied file spec.
  597.  
  598.     The second parameter points to the location where the result path 
  599.     string should be stored, it can be NULL if the path is to be ignored.
  600.  
  601.     The third parameter is the size of the available space pointed to by 
  602.     the second parameter. If the second parameter is NULL, the value of 
  603.     this parameter is ignored.
  604.  
  605.     The fourth parameter points to the location where the result filename 
  606.     string should be stored, it can be NULL if the name is to be ignored.
  607.  
  608.     The fifth parameter is the size of the available space pointed to by 
  609.     the fourth parameter. If the fourth parameter is NULL, the value of 
  610.     this parameter is ignored.
  611.  
  612.  
  613.     It returns TRUE if successful, FALSE otherwise.
  614. */
  615. {
  616.     int        pathlen, namelen, i, last = -1, colon = -1;
  617.  
  618.     if (spec == NULL) {
  619.         return(FALSE);
  620.     }
  621.  
  622.     for (i = 0; spec[i] != '\0'; i++) {
  623.         if (spec[i] == OFILE_SEPCHAR) {
  624.             last = i;
  625.         }
  626.         else if (spec[i] == ':') {
  627.             colon = i;
  628.         }
  629.     }
  630.  
  631.     if (last != -1) {    /*  path and name provided  */
  632.         pathlen = last + 1;
  633.         namelen = strlen(spec + last + 1);
  634.  
  635.         if (path != NULL) {
  636.             if (pathlen < maxpath) {
  637.                 strncpy(path, spec, pathlen);
  638.                 path[pathlen] = '\0';
  639.             }
  640.             else {
  641.                 return(FALSE);
  642.             }
  643.         }
  644.         if (name != NULL) {
  645.             if (namelen < maxname) {
  646.                 strcpy(name, spec + last + 1);
  647.             }
  648.             else {
  649.                 return(FALSE);
  650.             }
  651.         }
  652.     }
  653.     else {                /*  only name provided  */
  654.         if (colon == -1) {
  655.             if (path != NULL) {
  656.                 *path = '\0';
  657.             }
  658.             if (name != NULL) {
  659.                 if ((int)strlen(spec) < maxname) {
  660.                     strcpy(name, spec);
  661.                 }
  662.                 else {
  663.                     return(FALSE);
  664.                 }
  665.             }   
  666.         }
  667.         else {    /*  there is a colon but no slash's  */
  668.             pathlen = colon + 1;
  669.             namelen = strlen(spec + colon + 1);
  670.  
  671.             if (path != NULL) {
  672.                 if (pathlen < maxpath) {
  673.                     strncpy(path, spec, pathlen);
  674.                     path[pathlen] = '\0';
  675.                 }
  676.                 else {
  677.                     return(FALSE);
  678.                 }
  679.             }
  680.             if (name != NULL) {
  681.                 if (namelen < maxname) {
  682.                     strcpy(name, spec + colon + 1);
  683.                 }
  684.                 else {
  685.                     return(FALSE);
  686.                 }
  687.             }
  688.         }
  689.     }
  690.     return(TRUE);
  691. }
  692. /* -------------------------------------------------------------------------- */
  693.  
  694. boolean os2dir_Join(char *spec, int maxspec, char *path, char *name)
  695. /*
  696.     This routine connects a string representing the path of a spec and 
  697.     a string representing the filename of a spec to form a string representing
  698.     a complete file spec.  It does no checking with    the directory system to 
  699.     verify either of the paths or the filename are valid; 
  700.     It simply minipulates the strings.  The first and third parameters or 
  701.     the first and fourth parameters are allowed to point to the same space
  702.     since they may all be paths.
  703.  
  704.     The first parameter points to the location where the result spec 
  705.     string should be stored.
  706.  
  707.     The second parameter is the size of the available space pointer to by 
  708.     the first parameter.
  709.  
  710.     The third parameter is the supplied path.
  711.  
  712.     The fourth parameter is the supplied filename.
  713.  
  714.     It returns TRUE if successful, FALSE otherwise.
  715. */
  716. {                
  717.     int        pathlen, namelen;
  718.     char    strbuf[OFILE_PATHLEN];
  719.  
  720.     pathlen = strlen(path);
  721.     namelen = strlen(name);
  722.  
  723.     if (pathlen + namelen < maxspec) {
  724.         strcpy(strbuf, path);
  725.         strcat(strbuf, name);
  726.         strcpy(spec, strbuf);
  727.         return(TRUE);
  728.     }
  729.     else {
  730.         return(FALSE);
  731.     }
  732. /* -------------------------------------------------------------------------- */
  733.  
  734. char *os2dir_StripCase(char *str)
  735. /*
  736.     This function converts all uppercase characters in the supplied string 
  737.     into lowercase.
  738. */
  739. {
  740.     for (; *str != '\0'; str++) {
  741.         *str = (char)otolower(*str);
  742.     }
  743.     return(str);
  744. }
  745. /* -------------------------------------------------------------------------- */
  746.  
  747. boolean os2dir_GetCurrDir(char *buf, int len)
  748. {
  749.     ULONG    dmap;
  750.     USHORT    dnum, buflen;
  751.  
  752.     DosQCurDisk(&dnum, &dmap);
  753.     buflen = len;
  754.  
  755.     if (DosQCurDir(dnum, buf + 1, &buflen) == 0) {
  756.         *buf = OFILE_SEPCHAR;
  757.  
  758.         return(TRUE);
  759.     }
  760.     return(FALSE);
  761. }
  762.