/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- path_split
- 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);
}