home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / source / util2src / makepath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-21  |  6.9 KB  |  164 lines

  1. /*============================================================================*
  2.  * module: makepath.c - Make a path.
  3.  *
  4.  * (C)Copyright IBM Corporation, 1992                      Brian E. Yoder
  5.  *
  6.  * Functions contained in this module for use by external programs:
  7.  *   makepath() - Make a path when one of its directories doesn't exist.
  8.  *
  9.  * 09/21/92 - Created.
  10.  * 09/21/92 - Initial version.
  11.  *============================================================================*/
  12. #define LINT_ARGS
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <sys/types.h>
  18.  
  19. //nclude <dir.h>                    /* AIX */
  20. #include <direct.h>                 /* DOS, OS/2 */
  21.  
  22. #include "util.h"
  23.  
  24. #define SEP        '\\'     /* Path separator character */
  25.  
  26. #ifndef PATH_MAX            /* Max. length of a full pathname */
  27. #define PATH_MAX 1024
  28. #endif
  29.  
  30. /* Mode mask for mkdir() system subroutine (AIX only) */
  31.  
  32. #define MK_MASK    (S_IRWXU | S_IRWXG | S_IRWXO)
  33.  
  34. /*---------------------------------------------------------------------------*
  35.  * IsDotDir(fname) returns true if fname is "." or ".."
  36.  *---------------------------------------------------------------------------*/
  37.  
  38. #ifndef IsDotDir
  39. #define IsDotDir(fname) ((fname)[0] == '.' && (((fname)[1] == '\0') || \
  40.                         ((fname)[1] == '.' && (fname)[2] == '\0')))
  41. #endif
  42.  
  43. /*============================================================================*
  44.  * makepath() - Make a path when one of its directories doesn't exist.
  45.  *
  46.  * Purpose:
  47.  *   This subroutine takes the full or relative pathname of a file.
  48.  *   It assumes that there is path information and that one or more
  49.  *   directories within the path do not exist.  It also assumes that
  50.  *   the last component of the path is the name of the file itself.
  51.  *   The pathname may also end with a path separator, implying that no
  52.  *   filename is present.
  53.  *
  54.  *   This subroutine checks each directory in the path, starting with
  55.  *   the first one.  When it finds a directory that doesn't exist,
  56.  *   it uses the mkdir() system call to make the directory and all
  57.  *   directories that follow.
  58.  *
  59.  *   For example, assume that you pass the path '/u/fred/dir1/dir2/fname'
  60.  *   to makepath() and that 'dir', 'dir2', and, of course, 'fname' do not
  61.  *   exist.  This subroutine will make the '/u/fred/dir1' directory and
  62.  *   then make the '/u/fred/dir1/dir2' directory.
  63.  *
  64.  * Returns:
  65.  *   0, if no errors.  Nonzero, if an error occurred.
  66.  *============================================================================*/
  67.  
  68. int makepath(path)
  69.  
  70. char  *path;                 /* Pointer to 'path/name' of a file */
  71.  
  72. {
  73.   char  work[PATH_MAX+1];    /* Store 'path/name' here to work on it */
  74.  
  75.   char *lastsep;             /* Pointer to last path separator before 'name' */
  76.   char *sep;                 /* Pointer to current path separator position */
  77.   char *nextdir;             /* Pointer to next (possibly-nonexistent) dir */
  78.  
  79.   int   mkflag = FALSE;      /* TRUE=make dir, FALSE=check 1st: it may exist */
  80.   int   mkrc;                /* Store return code from mkdir() here */
  81.  
  82.  /*=====================================================================*
  83.   * Store 'path' in 'work' buffer, after making sure it's not too long
  84.   *=====================================================================*/
  85.  
  86.   if ((ulong)strlen(path) > (ulong)PATH_MAX)
  87.      return(2);
  88.  
  89.   strcpy(work, path);              /* Store path string in buffer */
  90.  
  91.   lastsep = strrchr(work, SEP);    /* Store location of last separator */
  92.   if (lastsep == NULL)             /* If there are no path separators: */
  93.      return(0);                    /*    Return: there's nothing to do */
  94.  
  95.   *lastsep = '\0';                 /* Terminate string at end of last dir */
  96.  
  97.   nextdir = work;                  /* Point to name of first directory */
  98.   if (*nextdir == SEP)             /* Skip leading '/' if present */
  99.      nextdir++;
  100.  
  101.  /*=====================================================================*
  102.   * Loop to find the first directory that's not there.  When we find it,
  103.   * we will set 'mkflag' to YES.
  104.   *
  105.   * The following pointers are used:
  106.   *  lastsep
  107.   *     Points to the last path separator, just before the filename.
  108.   *     A null byte has been stored in this position, so we are effectively
  109.   *     elminating the filename and working only with the directory(ies).
  110.   *
  111.   *  sep
  112.   *     Used to point to the current separator we are working with.
  113.   *     We will use it to isolate the first part of the path with
  114.   *     the rest of the path.  The first part of the path may contain
  115.   *     at most one (the last one) directory that doesn't exist, or else
  116.   *     mkdir() won't be able to create a directory.
  117.   *
  118.   *  nextdir
  119.   *     Points to the last directory before 'sep'.  We only need to look
  120.   *     at it to see if it's '.' or '..' since these are valid directories
  121.   *     and can be skipped over.
  122.   *=====================================================================*/
  123.  
  124.   for (;;)                  /* Loop to make each directory in the path */
  125.   {
  126.      sep = strchr(nextdir, SEP);   /* Store location of next separator */
  127.      if (sep == NULL)              /* Note: if 'sep' is NULL, then we must */
  128.         sep = lastsep;             /* point to the end of the path */
  129.  
  130.      *sep = '\0';                  /* Terminate path at current seperator */
  131.  
  132.      if (!IsDotDir(nextdir))       /* If not . or .., then check it out: */
  133.      {
  134.         mkrc = 0;                        /* Init to 'no mkdir() error' */
  135.         if (mkflag == FALSE)             /* If we don't know to mkdir or not: */
  136.         {
  137.            if (!isdir(work))                 /* See if directory exists: */
  138.            {                                 /* If it doesn't exist: */
  139.               mkflag = TRUE;                     /* No more will, either */
  140.             //mkrc = mkdir(work, MK_MASK);       /* Make the directory (AIX-style) */
  141.               mkrc = mkdir(work);                /* Make the directory (DOS-style) */
  142.            }
  143.         }
  144.         else                             /* mkflag is TRUE: Skip isdir() test */
  145.         {
  146.          //mkrc = mkdir(work, MK_MASK);      /* Make the directory (AIX-style) */
  147.            mkrc = mkdir(work);               /* Make the directory (DOS-style) */
  148.         }
  149.         if (mkrc != 0)                   /* If we failed mkdir(): */
  150.            return(2);                        /* Return with error */
  151.      }                             /* Endif . or .. */
  152.  
  153.      if (sep == lastsep)           /* If there are no more dirs in path: */
  154.         break;                     /*    We're done: break out of loop */
  155.  
  156.      *sep = SEP;                   /* Put separator back */
  157.      nextdir = sep + 1;            /* Next directory to check is past the */
  158.                                    /*    current separator */
  159.  
  160.   }                         /* end of for loop */
  161.  
  162.   return(0);
  163. }
  164.