librnr  1.14.5
RoadNarrows Robotics Common Library 1
path.c File Reference

General file name and file path utilities. More...

#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <pwd.h>
#include "rnr/rnrconfig.h"
#include "rnr/dliststr.h"
#include "rnr/log.h"
#include "rnr/new.h"
#include "rnr/path.h"

Go to the source code of this file.

Classes

struct  path_iter
 

Macros

#define is1stidentifier(c)   (isapha((int)c) || ((c) == '_'))
 first id char More...
 
#define isidentifier(c)   (isalnum((int)c) || ((c) == '_'))
 id char
 

Functions

static DListStr_T * NewSearchPathDList (const char *sSearchPath)
 Build a dlist of canonical search paths. More...
 
char * NewExpandTilde (const char *sTildeExpr)
 Expand tilde expression. More...
 
char * NewSearchPathExpanded (const char *sSearchPath)
 Expands search path. More...
 
char * NewSearchPathCanonicalized (const char *sSearchPath)
 Expands and canonicalizes a search path. More...
 
PathIter_TSearchPathIterNew (const char *sSearchPath)
 Allocates and initilized a new search path iterator. More...
 
void SearchPathIterDelete (PathIter_T *pIter)
 Deletes search path iterator. More...
 
char * SearchPathIterFirst (PathIter_T *pIter, const char *sSearchFile)
 Get the first concatenated file path. More...
 
char * SearchPathIterNext (PathIter_T *pIter)
 Construct next file path from search path and search file name. More...
 
char * NewNormPath (const char *sPath)
 Normalize path. More...
 
char * NewRealPath (const char *sPath)
 Expands and canonicalizes a real path. More...
 
char * NewJoinedPath (const char *sPath1, const char *sPath2)
 Join two file paths. More...
 

Detailed Description

General file name and file path utilities.

LastChangedDate
2011-11-18 13:30:34 -0700 (Fri, 18 Nov 2011)
Rev
1577

Boths posix (the world) and Microsoft's file and path syntax are supported.

Author
Robin Knight (robin.nosp@m..kni.nosp@m.ght@r.nosp@m.oadn.nosp@m.arrow.nosp@m.s.co.nosp@m.m)

Definition in file path.c.

Macro Definition Documentation

#define is1stidentifier (   c)    (isapha((int)c) || ((c) == '_'))

first id char

Legal identifier character

Definition at line 70 of file path.c.

Function Documentation

char* NewExpandTilde ( const char *  sTildeExpr)

Expand tilde expression.

Parameters
sTildeExpr'~' [user]
Returns
Return allocated expanded tilde expression path on success.
If the expression has invalid syntax or the user does not exist, then NULL is returned.

Definition at line 157 of file path.c.

References DIR_SEP_CHAR, new_strdup(), NULL, and PATH_SEP_CHAR.

Referenced by NewSearchPathExpanded(), and PathIsAbsolute().

158 {
159  char *sUser;
160  struct passwd *pPassEntry;
161  uid_t uid;
162  char *sExpanded = NULL;
163 
164  // expression must start with a tilde
165  if( (sTildeExpr == NULL) || (*sTildeExpr != '~') )
166  {
167  return NULL;
168  }
169 
170  // user name
171  sUser = (char *)sTildeExpr + 1;
172 
173  // expand this user's home
174  if( (*sUser == 0) || (*sUser == DIR_SEP_CHAR) || (*sUser == PATH_SEP_CHAR) )
175  {
176  if( (sExpanded = getenv("HOME")) == NULL )
177  {
178  uid = getuid();
179  if( (pPassEntry = getpwuid(uid)) != NULL )
180  {
181  sExpanded = pPassEntry->pw_dir;
182  }
183  }
184  }
185 
186  // expand other user's home
187  else
188  {
189  if( (pPassEntry = getpwnam(sUser)) != NULL )
190  {
191  sExpanded = pPassEntry->pw_dir;
192  }
193  }
194 
195  if( sExpanded != NULL )
196  {
197  return new_strdup(sExpanded);
198  }
199  else
200  {
201  return NULL;
202  }
203 }
#define DIR_SEP_CHAR
directory component separator (char version)
Definition: rnrconfig.h:238
char * new_strdup(const char *s)
Duplicate a string.
Definition: new.c:176
#define NULL
null pointer
Definition: rnrconfig.h:199
#define PATH_SEP_CHAR
path separator (char version)
Definition: rnrconfig.h:236
char* NewJoinedPath ( const char *  sPath1,
const char *  sPath2 
)

Join two file paths.

The paths are expanded and canonicalized. The paths do not have to exist. If the second, appended path is an absolute path, then the joined path is the second path.

Parameters
sPath1Front absolute/relative path.
sPath2Appended, back end path.
Returns
On success, an allocated, canonical joined path name is returned.
On failure, NULL is returned.

Definition at line 802 of file path.c.

References DIR_SEP_STR, LOGERROR, NewSearchPathCanonicalized(), NEWSTR, NULL, and PathIsAbsolute().

Referenced by PathIsAbsolute().

803 {
804  char *p1 = NULL;
805  char *p2 = NULL;
806  char *pj = NULL;
807 
808  // canonicalize path 2
809  if( (p2 = NewSearchPathCanonicalized(sPath2)) == NULL )
810  {
811  LOGERROR("NewSearchPathCanonicalized(\"%s\") failed.", sPath2);
812  }
813 
814  // if the second path is an absolute path, cannot join
815  else if( PathIsAbsolute(p2) )
816  {
817  return p2;
818  }
819 
820  // canonicalize path 1
821  else if( (p1 = NewSearchPathCanonicalized(sPath1)) == NULL )
822  {
823  LOGERROR("NewSearchPathCanonicalized(\"%s\") failed.", sPath1);
824  }
825 
826  // join
827  else
828  {
829  pj = NEWSTR(strlen(p1)+strlen(DIR_SEP_STR)+strlen(p2));
830  sprintf(pj, "%s%s%s", p1, DIR_SEP_STR, p2);
831  }
832 
833  delete(p1);
834  delete(p2);
835 
836  return pj;
837 }
INLINE_IN_H bool_t PathIsAbsolute(const char *sPath)
Check if the given path is an absolute path.
Definition: path.h:91
#define DIR_SEP_STR
directory component separator (string version)
Definition: rnrconfig.h:239
#define NEWSTR(len)
Allocate new string buffer of length len+1.
Definition: new.h:64
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
char * NewSearchPathCanonicalized(const char *sSearchPath)
Expands and canonicalizes a search path.
Definition: path.c:331
char* NewNormPath ( const char *  sPath)

Normalize path.

Normalize path, eliminating double slashes and simplifying dot "." current and ".." parent directory references.

The path does not have to exist.

Returns
Returns allocated normalized path.

Definition at line 572 of file path.c.

References DIR_SEP_CHAR, DIR_SEP_STR, new_strdup(), NEWSTR, and PathIsAbsolute().

Referenced by NewSearchPathCanonicalized(), and PathIsAbsolute().

573 {
574  char *sTopDir;
575  char *sNew;
576  int i, j, k;
577  int slashes;
578 
579  // Degenerative empty string case.
580  if( *sPath == 0 )
581  {
582  return new_strdup(".");
583  }
584 
585  // Normalization results in a smaller length string, except in the
586  // degenerative case above.
587  sNew = NEWSTR(strlen(sPath));
588 
589  // The (implicit) top directory is either the root or current directory.
590  if( PathIsAbsolute(sPath) )
591  {
592  sTopDir = DIR_SEP_STR;
593  }
594  else
595  {
596  sTopDir = ".";
597  }
598 
599  //
600  // Normalize the path.
601  //
602  for(i=0, j=0; sPath[i]!=0; )
603  {
604  switch( sPath[i] )
605  {
606  //
607  // Potential current dot or parent dotdot directory path component.
608  //
609  case '.':
610  // "filename." or "filename.."
611  if( (j > 0) && (sNew[j-1] != DIR_SEP_CHAR) )
612  {
613  sNew[j++] = sPath[i++];
614  }
615 
616  // "../[path]" or ".."
617  else if( (sPath[i+1] == '.') &&
618  ((sPath[i+2] == DIR_SEP_CHAR) || (sPath[i+2] == 0)) )
619  {
620  //
621  // Try to backup to parent directory.
622  // example 1: "path1/pdir/cdir/../path2" -> "pathl/pdir/path2"
623  // example 2: "pdir/cdir/../path2" -> "pdir/path2"
624  // example 3: "cdir/../path2" -> "path2"
625  // example 4: "/cdir/../path2" -> "/path2"
626  // example 5: " cdir/../../path2" -> "../path2"
627  // example 6: "/cdir/../../path2" -> "/path2"
628  // example 7: "dir/../cdir/.." -> "."
629  //
630  for(k=j-1, slashes=0; k>=0 && slashes<2; --k)
631  {
632  if( sNew[k] == DIR_SEP_CHAR )
633  {
634  ++slashes;
635  }
636  }
637  ++k;
638 
639  // i i
640  // k j k j
641  // "[path/]pdir/cdir/..[/path]" or "[path/]pdir/../..[/path]"
642  //
643  if( slashes == 2 )
644  {
645  // if current directory is "..", then "../.."
646  if( (sNew[k+1] == '.') &&
647  (sNew[k+2] == '.') &&
648  (sNew[k+3] == DIR_SEP_CHAR) )
649  {
650  sNew[j++] = '.';
651  sNew[j++] = '.';
652  }
653  // "[path]/pdir"
654  else
655  {
656  j = k;
657  sNew[j] = 0;
658  }
659  }
660 
661  // i i
662  // kj k j
663  // "/..[/path]" or "cdir/..[/path]"
664  //
665  else if( slashes == 1 )
666  {
667  // relative
668  if( sNew[0] != DIR_SEP_CHAR )
669  {
670  j = 0;
671  sNew[j++] = '.';
672  sNew[j] = 0;
673  }
674  // absolute
675  else
676  {
677  j = 0;
678  sNew[j++] = DIR_SEP_CHAR;
679  sNew[j] = 0;
680  }
681  }
682 
683  // i
684  // j
685  // k
686  // "..[/path]"
687  //
688  else // slashes == 0
689  {
690  j = 0;
691  sNew[j++] = '.';
692  sNew[j++] = '.';
693  sNew[j] = 0;
694  }
695 
696  i += 2;
697  }
698 
699  // current dot directory "./[path]" or "."
700  else if( (sPath[i+1] == DIR_SEP_CHAR) || (sPath[i+1] == 0) )
701  {
702  i += sPath[i+1] == DIR_SEP_CHAR? 2: 1;
703  }
704 
705  // dot filename ".filename"
706  else
707  {
708  sNew[j++] = sPath[i++];
709  }
710  break;
711 
712  //
713  // Directory component.
714  //
715  case DIR_SEP_CHAR:
716  // directory separator that's not superfluous "[path1]/path2"
717  if( (sPath[i+1] != DIR_SEP_CHAR) && (sPath[i+1] != 0) )
718  {
719  // "/[path]"
720  if( j == 0 )
721  {
722  sNew[j++] = sPath[i++];
723  }
724  // "//path}
725  else if( sNew[j-1] == DIR_SEP_CHAR )
726  {
727  ++i;
728  }
729  // "[path1/]./[path2]"
730  else if((sNew[j-1] == '.') &&
731  ((j == 1) || (sNew[j-2] == DIR_SEP_CHAR)) )
732  {
733  --j;
734  ++i;
735  }
736  // "[path1]/path2"
737  else
738  {
739  sNew[j++] = sPath[i++];
740  }
741  }
742  // ignore extra or ending separator "//" or "/"
743  else
744  {
745  ++i;
746  }
747  break;
748 
749  //
750  // Non-special file character.
751  //
752  default:
753  sNew[j++] = sPath[i++];
754  break;
755  }
756  }
757 
758  sNew[j] = 0;
759 
760  if( *sNew == 0 )
761  {
762  strcpy(sNew, sTopDir);
763  }
764 
765  return sNew;
766 }
#define DIR_SEP_CHAR
directory component separator (char version)
Definition: rnrconfig.h:238
INLINE_IN_H bool_t PathIsAbsolute(const char *sPath)
Check if the given path is an absolute path.
Definition: path.h:91
#define DIR_SEP_STR
directory component separator (string version)
Definition: rnrconfig.h:239
#define NEWSTR(len)
Allocate new string buffer of length len+1.
Definition: new.h:64
char * new_strdup(const char *s)
Duplicate a string.
Definition: new.c:176
char* NewRealPath ( const char *  sPath)

Expands and canonicalizes a real path.

The expanded path must exist.

Parameters
sPathPath file name.
Returns
Return allocated canonical path on success, NULL if path doest not exist.

Definition at line 778 of file path.c.

References NewSearchPathCanonicalized(), and NULL.

Referenced by PathIsAbsolute().

779 {
780  char *s, *t;
781 
782  s = NewSearchPathCanonicalized(sPath);
783  t = realpath(s, NULL);
784  delete(s);
785  return t;
786 }
#define NULL
null pointer
Definition: rnrconfig.h:199
char * NewSearchPathCanonicalized(const char *sSearchPath)
Expands and canonicalizes a search path.
Definition: path.c:331
char* NewSearchPathCanonicalized ( const char *  sSearchPath)

Expands and canonicalizes a search path.

The path does not have to exist.

A canonical search path has:

  • any beginning or ending path separators stipped
  • any contiguous sequence of path separators replaced with a single separator
  • any contiguous sequence of directory separators replaced with a single separator
  • any terminating directory separator stripped from each path component
Parameters
sSearchPathSearch path of form: path [path_sep path...]
Returns
Return allocated canonical search path on success, NULL if search path is is not specified. If the search path is too long, a truncated version will be returned.

Definition at line 331 of file path.c.

References NewNormPath(), NewSearchPathExpanded(), NEWSTR, NULL, and PATH_SEP_STR.

Referenced by NewJoinedPath(), NewRealPath(), NewSearchPathDList(), PathIsAbsolute(), and SearchPathIterFirst().

332 {
333  char *sExpPath; // expanded search path
334  char *sPath; // expanded path
335  char *sNorm; // normalized path
336  char *sSep; // path separator
337  char *sNew; // canonical search path
338  char *sSave = NULL; // strtok() save pointer
339  char *s; // working string
340  size_t k, m, n, len; // working sizes
341 
342  // expand any environment variables and '~''s listed in search path
343  if( (sExpPath = NewSearchPathExpanded(sSearchPath)) == NULL )
344  {
345  return NULL;
346  }
347 
348  len = strlen(sExpPath);
349  sNew = NEWSTR(len);
350  n = 0;
351  sSep = "";
352  k = 0;
353 
354  for(sPath=strtok_r(sExpPath, PATH_SEP_STR, &sSave);
355  sPath!=NULL;
356  sPath=strtok_r(NULL, PATH_SEP_STR, &sSave))
357  {
358  sNorm = NewNormPath(sPath);
359  m = strlen(sNorm);
360 
361  // grow new search path
362  if( n+k+m >= len )
363  {
364  len = (n + k + m) * 2;
365  s = NEWSTR(len);
366  strcpy(s, sNew);
367  delete(sNew);
368  sNew = s;
369  }
370 
371  sprintf(sNew+n, "%s%s", sSep, sNorm);
372  n += k + m;
373 
374  if( *sSep == 0 )
375  {
376  sSep = PATH_SEP_STR;
377  k = strlen(sSep);
378  }
379  }
380 
381  delete(sExpPath);
382 
383  return sNew;
384 }
#define NEWSTR(len)
Allocate new string buffer of length len+1.
Definition: new.h:64
char * NewSearchPathExpanded(const char *sSearchPath)
Expands search path.
Definition: path.c:227
#define NULL
null pointer
Definition: rnrconfig.h:199
#define PATH_SEP_STR
path separator (string version)
Definition: rnrconfig.h:237
char * NewNormPath(const char *sPath)
Normalize path.
Definition: path.c:572
static DListStr_T* NewSearchPathDList ( const char *  sSearchPath)
static

Build a dlist of canonical search paths.

Parameters
sSearchPathSearch path of form: path [path_sep path...]
Returns
Returns new dlist of path components.

Definition at line 93 of file path.c.

References DListStrDataPrint(), DListStrNewDft(), LOG_GET_LOGFP(), LOG_LEVEL_DIAG4, LOGABLE, LOGDIAG4, LOGERROR, LOGFUNCNAME, NewSearchPathCanonicalized(), NULL, and PATH_SEP_STR.

Referenced by SearchPathIterNew().

94 {
95  DListStr_T *pSearchPaths; // list of search paths
96  char *sExpPath; // expanded path
97  char *sPath; // search path component
98  char *sSave = NULL; // strtok() save pointer
99 
100  // new dlist
101  if( (pSearchPaths = DListStrNewDft()) == NULL )
102  {
103  LOGERROR("DListStrNew() failed");
104  return NULL;
105  }
106 
107  // no search paths
108  if( (sSearchPath == NULL) || (sSearchPath[0] == 0) )
109  {
110  return pSearchPaths;
111  }
112 
113  // canonicalize expanded search path
114  if( (sExpPath = NewSearchPathCanonicalized(sSearchPath)) == NULL )
115  {
116  return pSearchPaths;
117  }
118 
119  // parse search path and append compenents to dlist
120  for(sPath=strtok_r(sExpPath, PATH_SEP_STR, &sSave);
121  sPath!=NULL;
122  sPath=strtok_r(NULL, PATH_SEP_STR, &sSave))
123  {
124  if( DListStrAppend(pSearchPaths, sPath) == NULL )
125  {
126  LOGERROR("DListStrAppend() failed");
127  break;
128  }
129  }
130 
131  delete(sExpPath);
132 
133  LOGDIAG4("%s(%s)", LOGFUNCNAME, sSearchPath);
134  if( LOGABLE(LOG_LEVEL_DIAG4) )
135  {
136  DListStrPrint(pSearchPaths, DListStrDataPrint, LOG_GET_LOGFP());
137  }
138 
139  return pSearchPaths;
140 }
FILE * LOG_GET_LOGFP()
Get current logging output stream file pointer.
Definition: log.c:301
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGFUNCNAME
function name
Definition: log.h:225
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
#define LOGABLE(level)
Test if given level is logable at current threshold.
Definition: log.h:195
#define LOGDIAG4(fmt,...)
Standard Diagnostic Level 4 logging.
Definition: log.h:386
#define PATH_SEP_STR
path separator (string version)
Definition: rnrconfig.h:237
char * NewSearchPathCanonicalized(const char *sSearchPath)
Expands and canonicalizes a search path.
Definition: path.c:331
static DListStr_T * DListStrNewDft()
Allocator and initializer new empty string dlist with default callbacks.
Definition: dliststr.h:91
static void DListStrDataPrint(FILE *fp, char *sData)
Print node data callback.
Definition: dliststr.h:74
#define LOG_LEVEL_DIAG4
diagnostic level 4
Definition: log.h:184
char* NewSearchPathExpanded ( const char *  sSearchPath)

Expands search path.

Expands any environment variables and tilde expressions in search path while building new search path.

The path does not have to exist.

Variable are specified as:
$<identifier> or ${<identifier>} where <identifier> is a legal shell variable name.

Tilde expressions are specified as:
~ or ~user

Parameters
sSearchPathSearch path of form: path [path_sep path...]
Returns
Return allocated expanded search path on success, NULL if search path is is not specified. If the search path is too long, a truncated version will be returned.

Definition at line 227 of file path.c.

References DIR_SEP_CHAR, isidentifier, LOGDIAG4, LOGERROR, LOGFUNCNAME, MAX_SEARCH_PATH, new_strndup(), NewExpandTilde(), NEWSTR, and NULL.

Referenced by NewSearchPathCanonicalized(), and PathIsAbsolute().

228 {
229  char *sExpPath; // expanded path
230  const char *s, *u; // working source char pointers
231  char *t; // working target char pointers
232  char *sName, *sVal; // environment name=value strings
233  size_t nExpLen = 0; // current length of expanded path
234  // (sans null character)
235  size_t nMaxLen = MAX_SEARCH_PATH-1; // maximum length
236  size_t nNameLen; // name length
237 
238  if( (sSearchPath == NULL) || (*sSearchPath == 0) )
239  {
240  return NULL;
241  }
242 
243  sExpPath = NEWSTR(nMaxLen);
244 
245  for(s=sSearchPath, t=sExpPath; *s && nExpLen<nMaxLen; )
246  {
247  switch(*s)
248  {
249  case '$':
250  ++s;
251  if( *s == '{' )
252  {
253  ++s;
254  }
255  for(u=s; isidentifier(*s); ++s);
256  sName = NULL;
257  nNameLen = (size_t)(s - u);
258  if( nNameLen > 0 )
259  {
260  sName = new_strndup(u, nNameLen);
261  if( (sName != NULL) && ((sVal = getenv(sName)) != NULL) )
262  {
263  for(; *sVal && nExpLen<nMaxLen; ++nExpLen)
264  {
265  *t++ = *sVal++;
266  }
267  }
268  delete(sName);
269  }
270  if( *s == '}' )
271  {
272  ++s;
273  }
274  break;
275  case '~':
276  for(u=s; (*s != DIR_SEP_CHAR) && (*s != 0); ++s);
277  sName = NULL;
278  nNameLen = (size_t)(s - u);
279  if( nNameLen > 0 )
280  {
281  sName = new_strndup(u, nNameLen);
282  if( (sName != NULL) && ((sVal = NewExpandTilde(sName)) != NULL) )
283  {
284  for(u=sVal; *u && nExpLen<nMaxLen; ++nExpLen)
285  {
286  *t++ = *u++;
287  }
288  delete(sVal);
289  }
290  delete(sName);
291  }
292  break;
293  default:
294  *t++ = *s++;
295  ++nExpLen;
296  break;
297  }
298  }
299  *t = 0;
300 
301  if( nExpLen >= nMaxLen )
302  {
303  LOGERROR("Expanded search path truncated");
304  }
305 
306  LOGDIAG4("'%s'=%s('%s')", sExpPath, LOGFUNCNAME, sSearchPath);
307 
308  return sExpPath;
309 }
#define DIR_SEP_CHAR
directory component separator (char version)
Definition: rnrconfig.h:238
char * new_strndup(const char *s, size_t n)
Duplicate not more than n characters of string.
Definition: new.c:208
#define NEWSTR(len)
Allocate new string buffer of length len+1.
Definition: new.h:64
char * NewExpandTilde(const char *sTildeExpr)
Expand tilde expression.
Definition: path.c:157
#define NULL
null pointer
Definition: rnrconfig.h:199
#define isidentifier(c)
id char
Definition: path.c:71
#define LOGFUNCNAME
function name
Definition: log.h:225
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
#define LOGDIAG4(fmt,...)
Standard Diagnostic Level 4 logging.
Definition: log.h:386
#define MAX_SEARCH_PATH
Maximum bytes of a PATH_SEP separated search path string (including NULL)
Definition: rnrconfig.h:222
void SearchPathIterDelete ( PathIter_T pIter)

Deletes search path iterator.

Parameters
pIterSearch path iterator (invalid after return from this call).

Definition at line 422 of file path.c.

References path_iter::m_pSearchPaths, path_iter::m_sFileCanonical, path_iter::m_sFilePath, and NULL.

Referenced by PathIsAbsolute(), and SearchPathIterNew().

423 {
424  if( pIter == NULL )
425  {
426  return;
427  }
428 
429  if( pIter->m_pSearchPaths != NULL )
430  {
431  DListStrDelete(pIter->m_pSearchPaths);
432  }
433 
434  delete(pIter->m_sFileCanonical);
435  delete(pIter->m_sFilePath);
436 
437  delete(pIter);
438 }
char * m_sFileCanonical
search canonical file
Definition: path.c:79
#define NULL
null pointer
Definition: rnrconfig.h:199
DListStr_T * m_pSearchPaths
dlist of search paths
Definition: path.c:78
char * m_sFilePath
concatenated file path (output)
Definition: path.c:81
char* SearchPathIterFirst ( PathIter_T pIter,
const char *  sSearchFile 
)

Get the first concatenated file path.

Initialize search path iterator from given search file and returns first concatenated file path.

Parameters
pIterPath iterator.
sSearchFileSearch path.
Returns
Returns first file path on success, NULL if at end of search or on error.

Definition at line 452 of file path.c.

References DIR_SEP_STR, LOGDIAG4, LOGERROR, LOGFUNCNAME, path_iter::m_bIsEos, path_iter::m_iterPaths, path_iter::m_nFileLen, path_iter::m_pSearchPaths, path_iter::m_sFileCanonical, path_iter::m_sFilePath, NewSearchPathCanonicalized(), NEWSTR, and NULL.

Referenced by PathIsAbsolute().

453 {
454  const char *sPath; // search path component
455  size_t nLen; // string length
456 
457  // logistics to [re]set iterator
458  delete(pIter->m_sFileCanonical); // clear any old canonical serach file
459  pIter->m_sFileCanonical = NULL;
460  delete(pIter->m_sFilePath); // clear any old constructed file path
461  pIter->m_sFilePath = NULL;
462  pIter->m_nFileLen = 0; // no file, no length
463  pIter->m_bIsEos = true; // assume end-of-search condition until
464  // proven otherwise
465 
466  // no serach file specified
467  if( (sSearchFile == NULL) || (*sSearchFile == 0) )
468  {
469  LOGERROR("%s(): no file specified", LOGFUNCNAME);
470  return NULL;
471  }
472 
473  // cannot canonicalize search file
474  else if( (pIter->m_sFileCanonical = NewSearchPathCanonicalized(sSearchFile))
475  == NULL )
476  {
477  LOGERROR("NewSearchPathCanonicalized() failed");
478  return NULL;
479  }
480 
481  // set canonical file name length - used to speed iteration
482  pIter->m_nFileLen = strlen(pIter->m_sFileCanonical);
483 
484  // no search path - just return canonical file
485  if( DListStrCount(pIter->m_pSearchPaths) == 0 )
486  {
487  LOGDIAG4("'%s'=%s()", pIter->m_sFileCanonical, LOGFUNCNAME);
488 
489  return pIter->m_sFileCanonical;
490  }
491 
492  // construct first file path
493  else if( (sPath = DListStrIterDataFirst(pIter->m_pSearchPaths,
494  &(pIter->m_iterPaths))) != NULL )
495  {
496  pIter->m_bIsEos = false;
497 
498  nLen = strlen(sPath) + strlen(DIR_SEP_STR) + pIter->m_nFileLen;
499 
500  pIter->m_sFilePath = NEWSTR(nLen);
501 
502  sprintf(pIter->m_sFilePath, "%s%s%s",
503  sPath, DIR_SEP_STR, pIter->m_sFileCanonical);
504 
505  LOGDIAG4("'%s'=%s()", pIter->m_sFilePath, LOGFUNCNAME);
506 
507  return pIter->m_sFilePath;
508  }
509 
510  // shouldn't have gotten here - so terminate search
511  else
512  {
513  return NULL;
514  }
515 }
#define DIR_SEP_STR
directory component separator (string version)
Definition: rnrconfig.h:239
bool_t m_bIsEos
is [not] end of search flag
Definition: path.c:83
#define NEWSTR(len)
Allocate new string buffer of length len+1.
Definition: new.h:64
size_t m_nFileLen
length of canonical file
Definition: path.c:80
char * m_sFileCanonical
search canonical file
Definition: path.c:79
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGFUNCNAME
function name
Definition: log.h:225
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
#define LOGDIAG4(fmt,...)
Standard Diagnostic Level 4 logging.
Definition: log.h:386
DListStr_T * m_pSearchPaths
dlist of search paths
Definition: path.c:78
char * m_sFilePath
concatenated file path (output)
Definition: path.c:81
char * NewSearchPathCanonicalized(const char *sSearchPath)
Expands and canonicalizes a search path.
Definition: path.c:331
DListStrIter_T m_iterPaths
dlist iterator over paths
Definition: path.c:82
PathIter_T* SearchPathIterNew ( const char *  sSearchPath)

Allocates and initilized a new search path iterator.

This iterator can be reused multiple times with different search files by calling SearchPathIterFirst(). SearchPathIterDelete() must be called when finished with the iterator to clean up any allocated memory.

Parameters
sSearchPathSearch path of form: path [path_sep path...]
Returns
Returns pointer to search path iterator on success, NULL on error

Definition at line 398 of file path.c.

References LOGERROR, path_iter::m_bIsEos, path_iter::m_nFileLen, path_iter::m_pSearchPaths, path_iter::m_sFileCanonical, path_iter::m_sFilePath, NEW, NewSearchPathDList(), NULL, and SearchPathIterDelete().

Referenced by PathIsAbsolute().

399 {
400  PathIter_T *pIter = NEW(PathIter_T);
401 
402  if( (pIter->m_pSearchPaths = NewSearchPathDList(sSearchPath)) == NULL )
403  {
404  LOGERROR("NewSearchPathDlist() failed");
405  SearchPathIterDelete(pIter);
406  return NULL;
407  }
408 
409  pIter->m_sFileCanonical = NULL;
410  pIter->m_nFileLen = 0;
411  pIter->m_sFilePath = NULL;
412  pIter->m_bIsEos = false;
413 
414  return pIter;
415 }
bool_t m_bIsEos
is [not] end of search flag
Definition: path.c:83
size_t m_nFileLen
length of canonical file
Definition: path.c:80
char * m_sFileCanonical
search canonical file
Definition: path.c:79
#define NULL
null pointer
Definition: rnrconfig.h:199
void SearchPathIterDelete(PathIter_T *pIter)
Deletes search path iterator.
Definition: path.c:422
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
DListStr_T * m_pSearchPaths
dlist of search paths
Definition: path.c:78
#define NEW(T)
Allocate new type.
Definition: new.h:49
char * m_sFilePath
concatenated file path (output)
Definition: path.c:81
Definition: path.c:76
static DListStr_T * NewSearchPathDList(const char *sSearchPath)
Build a dlist of canonical search paths.
Definition: path.c:93
char* SearchPathIterNext ( PathIter_T pIter)

Construct next file path from search path and search file name.

Parameters
pIterPath iterator.
Returns
Returns next constructed file path on success, NULL if at end of search or on error

Definition at line 526 of file path.c.

References DIR_SEP_STR, LOGDIAG4, LOGFUNCNAME, path_iter::m_bIsEos, path_iter::m_iterPaths, path_iter::m_nFileLen, path_iter::m_sFileCanonical, path_iter::m_sFilePath, NEWSTR, and NULL.

Referenced by PathIsAbsolute().

527 {
528  const char *sPath; // search path component
529  size_t nLen; // string length
530 
531  // end of search
532  if( pIter->m_bIsEos )
533  {
534  return NULL;
535  }
536 
537  // get the next search path component
538  else if( (sPath = DListStrIterDataNext(&(pIter->m_iterPaths))) != NULL )
539  {
540  nLen = strlen(sPath) + strlen(DIR_SEP_STR) + pIter->m_nFileLen;
541 
542  delete(pIter->m_sFilePath); // clear any old constructed file path
543  pIter->m_sFilePath = NEWSTR(nLen); // allocate new file path
544 
545  sprintf(pIter->m_sFilePath, "%s%s%s",
546  sPath, DIR_SEP_STR, pIter->m_sFileCanonical);
547 
548  LOGDIAG4("'%s'=%s()", pIter->m_sFilePath, LOGFUNCNAME);
549 
550  return pIter->m_sFilePath;
551  }
552 
553  // end of search
554  else
555  {
556  pIter->m_bIsEos = true;
557  return NULL;
558  }
559 }
#define DIR_SEP_STR
directory component separator (string version)
Definition: rnrconfig.h:239
bool_t m_bIsEos
is [not] end of search flag
Definition: path.c:83
#define NEWSTR(len)
Allocate new string buffer of length len+1.
Definition: new.h:64
size_t m_nFileLen
length of canonical file
Definition: path.c:80
char * m_sFileCanonical
search canonical file
Definition: path.c:79
#define NULL
null pointer
Definition: rnrconfig.h:199
#define LOGFUNCNAME
function name
Definition: log.h:225
#define LOGDIAG4(fmt,...)
Standard Diagnostic Level 4 logging.
Definition: log.h:386
char * m_sFilePath
concatenated file path (output)
Definition: path.c:81
DListStrIter_T m_iterPaths
dlist iterator over paths
Definition: path.c:82