## root/clib/path.c

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following definitions.

1. path_split
2. path_join

    /* Path parsing library module,
       Rick Smereka, Copyright (C) 2005-2006.

       This program is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation; either version 2 of the License, or
       (at your option) any later version.

       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       GNU General Public License for more details.

       You should have received a copy of the GNU General Public License
       along with this program; if not, get a copy via the Internet at
       http://gnu.org/copyleft/gpl.html or write to the Free Software
       Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       MA 02111-1307 USA

       You can contact the author via email at rsmereka@future-lab.com

       Original Linux version Dec/2005, Rick Smereka

       Ported to DOS, Windows, QNX and FreeBSD. Feb/2006, Rick Smereka */

    #include "stdhead.h"
    #include "path.h"

    int path_split(char *pin, int has_fname, char *drive, char *path, char *fname)
    {
       /* Split a path into it's component parts. Parts are returned
          in 'drive' (single character), 'path' and 'fname'. 'drive'
          is always 'EOS' in a Unix/Linux/QNX system. All components
          must be allocated to sufficient size by the caller. Paths must
          be supplied in absolute form, not in relative form. The
          last component of the path is assumed to be the file name.
          The flag 'has_fname' indicates whether a file name is
          present in the input path ('pin'). If the file name is not
          present, a NULL pointer may be passed for 'fname'.
          Function returns 'TRUE' upon success, 'FALSE' upon error. */

       char mname[] = "path_split";
       char *tmp;
       int len, nwords, i, j, opos, last_dir;

       // basic checks

       if (pin == (char *)NULL)
          {
          logman("%s:null[pin]", mname);
          return(FALSE);
          }

       len = strlen(pin);

       if (!len)
          {
          logman("%s:empty[pin]", mname);
          return(FALSE);
          }

       if (drive == (char *)NULL)
          {
          logman("%s:null[drive]", mname);
          return(FALSE);
          }

       *drive = EOS;

       if (path == (char *)NULL)
          {
          logman("%s:null[path]", mname);
          return(FALSE);
          }

       path[0] = EOS;

       if (has_fname)
          {
          if (fname == (char *)NULL)
             {
             logman("%s:null[fname]", mname);
             return(FALSE);
             }

          fname[0] = EOS;
          }

       // printf("%s:pin=%s,%d\n", mname, pin, len);

       /* path must contain a minimum of 3 words if the file name
          is present, 2 words otherwise */

       nwords = ll_words(pin, PATH_SEP);

       if (has_fname)
          {
          if (nwords < 3)
             {
             logman("%s:invalid path[pin] s/b min 3 words", mname);
             return(FALSE);
             }
          }
       else
          if (nwords < 2)
             {
             logman("%s:invalid path[pin] s/b min of 2 words", mname);
             return(FALSE);
             }

       /* isolate drive first, a colon in the second byte is required
          under DOS and Windows */

    #ifdef OS_WIN32
       if (pin[1] != ':')
          {
          logman("%s:drive ID must be present under Windows systems", mname);
          return(FALSE);
          }
    #endif

    #ifdef OS_DOS
       if (pin[1] != ':')
          {
          logman("%s:drive ID must be present under DOS systems", mname);
          return(FALSE);
          }
    #endif

    #ifdef OS_WIN32
       *drive = toupper(pin[0]);
    #endif

    #ifdef OS_DOS
       *drive = toupper(pin[0]);
    #endif

       // isolate the path next

       if ((tmp = (char *)malloc(len + 1)) == (char *)NULL)
          {
          logman("%s:alloc fail[tmp]", mname);
          return(FALSE);
          }

       // printf("%s:nwords=%d\n", mname, nwords);
       opos = 0;

       if (has_fname)
          last_dir = nwords - 1;
       else
          last_dir = nwords;

       // start from word 2

       for(i = 2; i <= last_dir; i++)
          {
          if (!ll_word(pin, tmp, i, PATH_SEP))
             {
             logman("%s:bad rc[FALSE] from ll_word[%d]", mname, i);
             free(tmp);
             return(FALSE);
             }

          // printf("%s:tmp[%d]=%s\n", mname, i, tmp);

          for(j = 0; tmp[j] != EOS; j++)
             path[opos++] = tmp[j];

          if (i < last_dir)
             path[opos++] = PATH_SEP;
          }

       path[opos] = EOS;
       free(tmp);

       // isolate the file name last

       if (has_fname)
          if (!ll_word(pin, fname, nwords, PATH_SEP))
             {
             logman("%s:bad rc from ll_word[%d]", mname, nwords);
             return(FALSE);
             }

       return(TRUE);
    }

    int path_join(char drive, char *path, char *fname, char *pout)
    {
       /* Join a path from it's component parts. In Windows and DOS,
          the 'drive' is required to be a single alphabetic character
          representing the drive ID. The 'path' must not begin with
          a path separator. Upon success, the joined path
          will be placed into 'pout' (this must be allocated to
          sufficient size by the caller). The file name ('fname')
          may be a NULL pointer which indicates no file name.
          Function returns 'TRUE' upon success, 'FALSE' otherwise. */

       char mname[] = "path_join";
       int has_fname;

       // check drive ID in Windows and DOS

    #ifdef OS_WIN32
       if (!isalpha(drive))
          {
          logman("%s:'%c' is not a valid drive letter", mname, drive);
          return(FALSE);
          }
    #endif

    #ifdef OS_DOS
       if (!isalpha(drive))
          {
          logman("%s:'%c' is not a valid drive letter", mname, drive);
          return(FALSE);
          }
    #endif

       // make sure 'path' does not start with separator

       if (path[0] == PATH_SEP)
          {
          logman("%s:'path' component must not start with separator", mname);
          return(FALSE);
          }

       // other checks

       if (path == (char *)NULL || !strlen(path))
          {
          logman("%s:null or empty[path]", mname);
          return(FALSE);
          }

       if (fname == (char *)NULL)
          has_fname = FALSE;

       if (has_fname && !strlen(fname))
          {
          logman("%s:empty[fname]", mname);
          return(FALSE);
          }

       // build final joined path

    #ifdef OS_WIN32
       if (has_fname)
          sprintf(pout, "%c:\\%s\\%s", drive, path, fname);
       else
          sprintf(pout, "%c:\\%s", drive, path);
    #endif

    #ifdef OS_DOS
       if (has_fname)
          sprintf(pout, "%c:\\%s\\%s", drive, path, fname);
       else
          sprintf(pout, "%c:\\%s", drive, path);
    #endif

    #ifdef OS_UNIX
       if (has_fname)
          sprintf(pout, "/%s/%s", path, fname);
       else
          sprintf(pout, "/%s", path);
    #endif

       return(TRUE);
    }

/* [<][>][^][v][top][bottom][index][help] */