util: Tidy header includes
[openafs.git] / src / util / dirpath.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #include <stddef.h>
16 #include <ctype.h>
17 #include <limits.h>
18
19 #include "afs_assert.h"
20 #include "afsutil.h"
21 #include "fileutil.h"
22
23 #ifdef AFS_PTHREAD_ENV
24 #include <pthread.h>
25 static pthread_once_t dirInit_once = PTHREAD_ONCE_INIT;
26 #endif
27
28 #ifdef AFS_NT40_ENV
29 #include <WINNT\afssw.h>
30 #endif
31
32 /* local vars */
33 /* static storage for path strings */
34 static char dirPathArray[AFSDIR_PATHSTRING_MAX][AFSDIR_PATH_MAX];
35
36 /* indicate if and how the dirpath module initialized. */
37 static int initFlag = 0;
38 static unsigned int initStatus = 0;
39
40
41 /* storage for dynamically-determined install dir (NT only; long and short) */
42 #ifdef AFS_NT40_ENV
43 static char ntServerInstallDirLong[AFSDIR_PATH_MAX];
44 static char ntServerInstallDirShort[AFSDIR_PATH_MAX];
45 static char ntClientConfigDirLong[AFSDIR_PATH_MAX];
46 static char ntClientConfigDirShort[AFSDIR_PATH_MAX];
47 #endif
48
49 /* storage for local afs server/client paths (top-level) */
50 static char afsSrvDirPath[AFSDIR_PATH_MAX];
51 static char afsClntDirPath[AFSDIR_PATH_MAX];
52
53 /* internal array init function */
54 static void initDirPathArray(void);
55
56 /* Additional macros for ease of use */
57 /* buf is expected to be atleast AFS_PATH_MAX bytes long */
58 #define AFSDIR_SERVER_DIRPATH(buf, dir)  \
59             (void) strcompose(buf, AFSDIR_PATH_MAX, serverPrefix, dir, NULL)
60
61 #define AFSDIR_SERVER_FILEPATH(buf, dir, file)  \
62             (void) strcompose(buf, AFSDIR_PATH_MAX, serverPrefix, dir, "/", file,  NULL)
63
64 #define AFSDIR_CLIENT_DIRPATH(buf, dir)  \
65             (void) strcompose(buf, AFSDIR_PATH_MAX, clientPrefix, dir, NULL)
66
67 #define AFSDIR_CLIENT_FILEPATH(buf, dir, file)  \
68             (void) strcompose(buf, AFSDIR_PATH_MAX,  clientPrefix, dir, "/", file,  NULL)
69
70
71 /* initAFSDirPath() -- External users call this function to initialize
72  * the dirpath module and/or to determine the initialization status.
73  */
74 unsigned int
75 initAFSDirPath(void)
76 {
77     if (initFlag == 0) {        /* not yet init'ed, so initialize */
78 #ifdef AFS_PTHREAD_ENV
79         pthread_once(&dirInit_once, initDirPathArray);
80 #else
81         initDirPathArray();
82 #endif
83     }
84     return initStatus;
85 }
86
87
88 /* initDirPathArray() -- Initializes the afs dir paths for the
89  *     server and client installations.
90  *
91  *     For NT these are determined dynamically; for Unix they are static.
92  *
93  *     NT NOTE: If a particular component (client/server) is not installed
94  *              then we may not be able to initialize the paths to anything
95  *              meaningful.  In this case the paths are set to the local
96  *              temp directory to avoid later reference to an uninitialized
97  *              variable.  The initStatus flag is set to indicate which
98  *              paths (client/server) initialized properly for callers of
99  *              initAFSDirPath() who would like to know this information.
100  */
101 static void
102 initDirPathArray(void)
103 {
104     char *pathp;
105     const char *clientPrefix = "";
106     const char *serverPrefix = "";
107
108 #ifdef AFS_NT40_ENV
109     char *buf;
110     int status;
111
112     /* get the afs server software installation dir from the registry */
113     if (afssw_GetServerInstallDir(&buf)) {
114         /* failed; server not installed; use temp directory */
115         strcpy(ntServerInstallDirLong, gettmpdir());
116     } else {
117         strcpy(ntServerInstallDirLong, buf);
118         free(buf);
119         initStatus |= AFSDIR_SERVER_PATHS_OK;
120     }
121     FilepathNormalize(ntServerInstallDirLong);
122     status =
123         GetShortPathName(ntServerInstallDirLong, ntServerInstallDirShort,
124                          AFSDIR_PATH_MAX);
125     if (status == 0 || status > AFSDIR_PATH_MAX) {
126         /* can't convert path to short version; just use long version */
127         strcpy(ntServerInstallDirShort, ntServerInstallDirLong);
128     }
129     FilepathNormalize(ntServerInstallDirShort);
130
131     /* get the afs client configuration directory (/usr/vice/etc equivalent) */
132     if (afssw_GetClientCellServDBDir(&buf)) {
133         /* failed */
134         status = GetWindowsDirectory(ntClientConfigDirLong, AFSDIR_PATH_MAX);
135         if (status == 0 || status > AFSDIR_PATH_MAX) {
136             /* failed to get canonical Windows directory; use temp directory */
137             strcpy(ntClientConfigDirLong, gettmpdir());
138         } else {
139             initStatus |= AFSDIR_CLIENT_PATHS_OK;
140         }
141     } else {
142         strcpy(ntClientConfigDirLong, buf);
143         free(buf);
144         initStatus |= AFSDIR_CLIENT_PATHS_OK;
145     }
146     FilepathNormalize(ntClientConfigDirLong);
147
148     status =
149         GetShortPathName(ntClientConfigDirLong, ntClientConfigDirShort,
150                          AFSDIR_PATH_MAX);
151     if (status == 0 || status > AFSDIR_PATH_MAX) {
152         /* can't convert path to short version; just use long version */
153         strcpy(ntClientConfigDirShort, ntClientConfigDirLong);
154     }
155     FilepathNormalize(ntClientConfigDirShort);
156     clientPrefix = ntClientConfigDirShort;
157
158     /* setup the root server directory path (/usr/afs equivalent) */
159     strcpy(afsSrvDirPath, ntServerInstallDirShort);
160     strcat(afsSrvDirPath, AFSDIR_CANONICAL_SERVER_AFS_DIRPATH);
161
162     /* there is no root client directory path (/usr/vice equivalent) */
163     afsClntDirPath[0] = '\0';
164
165     /* setup top level dirpath (/usr equivalent); valid for server ONLY */
166     strcpy(dirPathArray[AFSDIR_USR_DIRPATH_ID], ntServerInstallDirShort);
167     serverPrefix = ntServerInstallDirShort;
168     strcat(dirPathArray[AFSDIR_USR_DIRPATH_ID], AFSDIR_CANONICAL_USR_DIRPATH);
169
170 #else /* AFS_NT40_ENV */
171     /* setup the root server directory path */
172     strcpy(afsSrvDirPath, AFSDIR_CANONICAL_SERVER_AFS_DIRPATH);
173
174     /* setup the root client directory path */
175 #ifdef AFS_DARWIN_ENV
176     if (access(AFSDIR_ALTERNATE_CLIENT_VICE_DIRPATH, F_OK) == 0)
177         strcpy(afsClntDirPath, AFSDIR_ALTERNATE_CLIENT_VICE_DIRPATH);
178     else
179 #endif
180         strcpy(afsClntDirPath, AFSDIR_CANONICAL_CLIENT_VICE_DIRPATH);
181
182     /* setup top level dirpath; valid for both server and client */
183     strcpy(dirPathArray[AFSDIR_USR_DIRPATH_ID], AFSDIR_CANONICAL_USR_DIRPATH);
184
185     initStatus |= (AFSDIR_CLIENT_PATHS_OK | AFSDIR_SERVER_PATHS_OK);
186 #endif /* AFS_NT40_ENV */
187
188     /* now initialize various dir and file paths exported by dirpath module */
189
190     /* server dir paths */
191     strcpy(dirPathArray[AFSDIR_SERVER_AFS_DIRPATH_ID], afsSrvDirPath);
192
193     pathp = dirPathArray[AFSDIR_SERVER_ETC_DIRPATH_ID];
194     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_SERVER_ETC_DIR);
195
196     pathp = dirPathArray[AFSDIR_SERVER_BIN_DIRPATH_ID];
197     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_SERVER_BIN_DIR);
198
199     pathp = dirPathArray[AFSDIR_SERVER_CORES_DIRPATH_ID];
200     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_CORES_DIR);
201
202     pathp = dirPathArray[AFSDIR_SERVER_DB_DIRPATH_ID];
203     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_DB_DIR);
204
205     pathp = dirPathArray[AFSDIR_SERVER_LOGS_DIRPATH_ID];
206     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_LOGS_DIR);
207
208     pathp = dirPathArray[AFSDIR_SERVER_LOCAL_DIRPATH_ID];
209     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_LOCAL_DIR);
210
211     pathp = dirPathArray[AFSDIR_SERVER_BACKUP_DIRPATH_ID];
212     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_BACKUP_DIR);
213
214     pathp = dirPathArray[AFSDIR_SERVER_MIGRATE_DIRPATH_ID];
215     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_MIGR_DIR);
216
217     pathp = dirPathArray[AFSDIR_SERVER_BIN_FILE_DIRPATH_ID];
218     AFSDIR_SERVER_DIRPATH(pathp, AFSDIR_BIN_FILE_DIR);
219
220     /* client dir path */
221 #ifdef AFS_NT40_ENV
222     strcpy(dirPathArray[AFSDIR_CLIENT_VICE_DIRPATH_ID],
223            "/NoUsrViceDirectoryOnWindows");
224     strcpy(dirPathArray[AFSDIR_CLIENT_ETC_DIRPATH_ID],
225            ntClientConfigDirShort);
226 #else
227     strcpy(dirPathArray[AFSDIR_CLIENT_VICE_DIRPATH_ID], afsClntDirPath);
228
229     pathp = dirPathArray[AFSDIR_CLIENT_ETC_DIRPATH_ID];
230 #ifdef AFS_DARWIN_ENV
231     if (access(AFSDIR_ALTERNATE_CLIENT_ETC_DIR, F_OK) == 0)
232         AFSDIR_CLIENT_DIRPATH(pathp, AFSDIR_ALTERNATE_CLIENT_ETC_DIR);
233     else
234 #endif
235         AFSDIR_CLIENT_DIRPATH(pathp, AFSDIR_CLIENT_ETC_DIR);
236 #endif /* AFS_NT40_ENV */
237
238 #ifndef AFS_NT40_ENV
239     pathp = dirPathArray[AFSDIR_CLIENT_DATA_DIRPATH_ID];
240 #ifdef AFS_DARWIN_ENV
241     if (access(AFSDIR_ALTERNATE_CLIENT_DATA_DIR, F_OK) == 0)
242         AFSDIR_CLIENT_DIRPATH(pathp, AFSDIR_ALTERNATE_CLIENT_DATA_DIR);
243     else
244 #endif
245         AFSDIR_CLIENT_DIRPATH(pathp, AFSDIR_DATA_DIR);
246 #endif
247
248     /* server file paths */
249     pathp = dirPathArray[AFSDIR_SERVER_THISCELL_FILEPATH_ID];
250     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR,
251                            AFSDIR_THISCELL_FILE);
252
253     pathp = dirPathArray[AFSDIR_SERVER_CELLSERVDB_FILEPATH_ID];
254     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR,
255                            AFSDIR_CELLSERVDB_FILE);
256
257     pathp = dirPathArray[AFSDIR_SERVER_NOAUTH_FILEPATH_ID];
258     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NOAUTH_FILE);
259
260     pathp = dirPathArray[AFSDIR_SERVER_BUDBLOG_FILEPATH_ID];
261     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_BUDBLOG_FILE);
262
263     pathp = dirPathArray[AFSDIR_SERVER_TAPECONFIG_FILEPATH_ID];
264     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BACKUP_DIR, AFSDIR_TAPECONFIG_FILE);
265
266     pathp = dirPathArray[AFSDIR_SERVER_KALOGDB_FILEPATH_ID];
267     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_KALOGDB_FILE);
268
269     pathp = dirPathArray[AFSDIR_SERVER_KALOG_FILEPATH_ID];
270     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_KALOG_FILE);
271
272     pathp = dirPathArray[AFSDIR_SERVER_KADB_FILEPATH_ID];
273     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_KADB_FILE);
274
275     pathp = dirPathArray[AFSDIR_SERVER_NTPD_FILEPATH_ID];
276     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_BIN_DIR, AFSDIR_NTPD_FILE);
277
278     pathp = dirPathArray[AFSDIR_SERVER_PRDB_FILEPATH_ID];
279     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_PRDB_FILE);
280
281     pathp = dirPathArray[AFSDIR_SERVER_PTLOG_FILEPATH_ID];
282     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_PTLOG_FILE);
283
284     pathp = dirPathArray[AFSDIR_SERVER_KCONF_FILEPATH_ID];
285     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_KCONF_FILE);
286
287     pathp = dirPathArray[AFSDIR_SERVER_VLDB_FILEPATH_ID];
288     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_DB_DIR, AFSDIR_VLDB_FILE);
289
290     pathp = dirPathArray[AFSDIR_SERVER_VLOG_FILEPATH_ID];
291     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_VLOG_FILE);
292
293     pathp = dirPathArray[AFSDIR_SERVER_CORELOG_FILEPATH_ID];
294     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_CORE_FILE);
295
296     pathp = dirPathArray[AFSDIR_SERVER_SLVGLOG_FILEPATH_ID];
297     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_SLVGLOG_FILE);
298
299     pathp = dirPathArray[AFSDIR_SERVER_SALSRVLOG_FILEPATH_ID];
300     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_SALSRVLOG_FILE);
301
302     pathp = dirPathArray[AFSDIR_SERVER_SALVAGER_FILEPATH_ID];
303     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_BIN_DIR,
304                            AFSDIR_SALVAGER_FILE);
305
306     pathp = dirPathArray[AFSDIR_SERVER_SALSRV_FILEPATH_ID];
307     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_BIN_DIR,
308                            AFSDIR_SALSRV_FILE);
309
310     pathp = dirPathArray[AFSDIR_SERVER_SLVGLOCK_FILEPATH_ID];
311     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_SLVGLOCK_FILE);
312
313     pathp = dirPathArray[AFSDIR_SERVER_KEY_FILEPATH_ID];
314     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_KEY_FILE);
315
316     pathp = dirPathArray[AFSDIR_SERVER_ULIST_FILEPATH_ID];
317     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_ULIST_FILE);
318
319     pathp = dirPathArray[AFSDIR_SERVER_BOZCONF_FILEPATH_ID];
320     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BOSCONFIG_DIR, AFSDIR_BOZCONF_FILE);
321
322     pathp = dirPathArray[AFSDIR_SERVER_BOZCONFNEW_FILEPATH_ID];
323     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BOSCONFIG_DIR,
324                            AFSDIR_BOZCONFNEW_FILE);
325
326     pathp = dirPathArray[AFSDIR_SERVER_BOZLOG_FILEPATH_ID];
327     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_BOZLOG_FILE);
328
329     pathp = dirPathArray[AFSDIR_SERVER_BOZINIT_FILEPATH_ID];
330     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BOSCONFIG_DIR, AFSDIR_BOZINIT_FILE);
331
332     pathp = dirPathArray[AFSDIR_SERVER_BOSVR_FILEPATH_ID];
333     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_BOSSERVER_DIR, AFSDIR_BOSVR_FILE);
334
335     pathp = dirPathArray[AFSDIR_SERVER_VOLSERLOG_FILEPATH_ID];
336     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_VOLSERLOG_FILE);
337
338     pathp = dirPathArray[AFSDIR_SERVER_ROOTVOL_FILEPATH_ID];
339     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_ROOTVOL_FILE);
340
341     pathp = dirPathArray[AFSDIR_SERVER_HOSTDUMP_FILEPATH_ID];
342     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_HOSTDUMP_FILE);
343
344     pathp = dirPathArray[AFSDIR_SERVER_CLNTDUMP_FILEPATH_ID];
345     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_CLNTDUMP_FILE);
346
347     pathp = dirPathArray[AFSDIR_SERVER_CBKDUMP_FILEPATH_ID];
348     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_CBKDUMP_FILE);
349
350     pathp = dirPathArray[AFSDIR_SERVER_OLDSYSID_FILEPATH_ID];
351     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_OLDSYSID_FILE);
352
353     pathp = dirPathArray[AFSDIR_SERVER_SYSID_FILEPATH_ID];
354     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_SYSID_FILE);
355
356     pathp = dirPathArray[AFSDIR_SERVER_FILELOG_FILEPATH_ID];
357     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_FILELOG_FILE);
358
359     pathp = dirPathArray[AFSDIR_SERVER_AUDIT_FILEPATH_ID];
360     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_AUDIT_FILE);
361
362     pathp = dirPathArray[AFSDIR_SERVER_NETINFO_FILEPATH_ID];
363     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NETINFO_FILE);
364
365     pathp = dirPathArray[AFSDIR_SERVER_NETRESTRICT_FILEPATH_ID];
366     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_NETRESTRICT_FILE);
367
368     pathp = dirPathArray[AFSDIR_SERVER_WEIGHTING_CONSTANTS_FILEPATH_ID];
369     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR,
370                            AFSDIR_WEIGHTINGCONST_FILE);
371
372     pathp = dirPathArray[AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH_ID];
373     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR,
374                            AFSDIR_THRESHOLDCONST_FILE);
375
376     pathp = dirPathArray[AFSDIR_SERVER_MIGRATELOG_FILEPATH_ID];
377     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_MIGR_DIR, AFSDIR_MIGRATE_LOGNAME);
378
379     pathp = dirPathArray[AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID];
380     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_KRB_EXCL_FILE);
381
382     pathp = dirPathArray[AFSDIR_SERVER_FSSTATE_FILEPATH_ID];
383     AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_FSSTATE_FILE);
384
385     /* client file paths */
386 #ifdef AFS_NT40_ENV
387     strcpy(dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID],
388            "/NoUsrViceEtcThisCellFileOnWindows");
389     sprintf(dirPathArray[AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID], "%s/%s",
390             ntClientConfigDirShort, AFSDIR_CELLSERVDB_FILE_NTCLIENT);
391     strcpy(dirPathArray[AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID],
392            "/NoCellAliasOnWindows");
393 #else
394     pathp = dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID];
395     AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR,
396                            AFSDIR_THISCELL_FILE);
397
398     pathp = dirPathArray[AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID];
399     AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR,
400                            AFSDIR_CELLSERVDB_FILE);
401
402     pathp = dirPathArray[AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID];
403     AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR,
404                            AFSDIR_CELLALIAS_FILE);
405 #endif /* AFS_NT40_ENV */
406
407     pathp = dirPathArray[AFSDIR_CLIENT_NETINFO_FILEPATH_ID];
408     AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_NETINFO_FILE);
409
410     pathp = dirPathArray[AFSDIR_CLIENT_NETRESTRICT_FILEPATH_ID];
411     AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR,
412                            AFSDIR_NETRESTRICT_FILE);
413
414     initFlag = 1;               /* finished dirpath initialization */
415     return;
416 }
417
418 /* getDirPath - returns a const char pointer to the requested string
419  * from the internal path array.
420  * string_id - index into the path array
421  */
422 const char *
423 getDirPath(afsdir_id_t string_id)
424 {
425     /* check if the array has been initialized */
426     if (initFlag == 0) {        /* no it's not, so initialize */
427 #ifdef AFS_PTHREAD_ENV
428         pthread_once(&dirInit_once, initDirPathArray);
429 #else
430         initDirPathArray();
431 #endif
432     }
433     return (const char *)dirPathArray[string_id];
434 }
435
436 /*
437  * LocalizePathHead() -- Make path relative to local part
438  *
439  * ConstructLocalPath takes a path and a directory that path should
440  * be considered relative to.  There are two possible cases:
441  *
442  * The path is an absolute path.  In this case, the relative path
443  * is ignored.  We check the path for a prefix that represents a
444  * canonical path, and if one is found, we adjust the path to remove
445  * the prefix and adjust the directory to which it should be
446  * considered relative to be the local version of that canonical path.
447  *
448  * The path is a relative path.  In this case, we check to see if the
449  * directory to which it is relative represents a canonical path, and
450  * if so, we adjust that directory to be the local version of that
451  * canonical path.  The relative path itself is left unchanged.
452  */
453
454 /* The following array  maps cannonical parts to local parts.  It
455  * might  seem reasonable to  simply construct an array in parallel to
456  * dirpatharray  but it turns out you don't want translations for all
457  * local paths.
458 */
459
460 struct canonmapping {
461     const char *canonical;
462     const char *local;
463 };
464 static struct canonmapping CanonicalTranslations[] = {
465     {AFSDIR_CANONICAL_SERVER_ETC_DIRPATH, AFSDIR_SERVER_ETC_DIR},
466     {AFSDIR_CANONICAL_SERVER_LOGS_DIRPATH, AFSDIR_LOGS_DIR},
467     {AFSDIR_CANONICAL_SERVER_LOCAL_DIRPATH, AFSDIR_LOCAL_DIR},
468     {AFSDIR_CANONICAL_SERVER_BIN_DIRPATH, AFSDIR_SERVER_BIN_DIR},
469     {NULL, NULL}
470 };
471
472 static void
473 LocalizePathHead(const char **path, const char **relativeTo)
474 {
475      struct canonmapping *map;
476
477      if (**path == '/') {
478          for (map = CanonicalTranslations; map->local != NULL; map++) {
479              int canonlength = strlen(map->canonical);
480              if (strncmp(*path, map->canonical, canonlength) == 0) {
481                  (*path) += canonlength;
482                  if (**path == '/')
483                      (*path)++;
484                  *relativeTo = map->local;
485                  return;
486              }
487          }
488      } else {
489          for (map = CanonicalTranslations; map->local != NULL; map++) {
490              if (strcmp(*relativeTo, map->canonical) == 0) {
491                  *relativeTo = map->local;
492                  return;
493              }
494          }
495      }
496 }
497
498
499 #ifdef AFS_NT40_ENV
500 /* NT version of ConstructLocalPath() */
501
502 /*
503  * ConstructLocalPath() --  Convert a canonical (wire-format) path to a fully
504  *     specified local path.  Upon successful completion, *fullPathBufp is
505  *     set to an allocated buffer containing the fully specified local path
506  *     constructed from the cpath argument.
507  *
508  *     On NT, path construction proceeds as follows:
509  *         1) If cpath is fully qualified (i.e., starts with 'X:/') then the
510  *            path returned is equivalent to cpath.
511  *         2) If cpath begins with a drive letter but is not fully qualified,
512  *            i.e., it is drive relative, then the function fails with EINVAL.
513  *         3) If cpath begins with '/' (or '\') then the path returned is the
514  *            concatenation  AFS-server-install-dir + cpath after translating for localization.
515  *         4) Otherwise the path returned is the concatenation
516  *            AFS-server-install-dir + relativeTo + cpath.
517  *
518  *     Leading whitespace in cpath is ignored; the constructed path is
519  *     normalized (FilepathNormalize()).
520  *
521  * RETURN CODES: 0 if successful; errno code otherwise.
522  */
523 int
524 ConstructLocalPath(const char *cpath, const char *relativeTo,
525                    char **fullPathBufp)
526 {
527     int status = 0;
528     char *newPath = NULL;
529
530     if (initFlag == 0) {        /* dirpath module not yet initialized */
531 #ifdef AFS_PTHREAD_ENV
532         pthread_once(&dirInit_once, initDirPathArray);
533 #else
534         initDirPathArray();
535 #endif
536     }
537
538     *fullPathBufp = NULL;
539
540     while (isspace(*cpath)) {
541         cpath++;
542     }
543
544     LocalizePathHead(&cpath, &relativeTo);
545     if ((((*cpath >= 'a') && (*cpath <= 'z'))
546          || ((*cpath >= 'A') && (*cpath <= 'Z'))) && (*(cpath + 1) == ':')) {
547
548         /* cpath has a leading drive letter */
549         if ((*(cpath + 2) != '/') && (*(cpath + 2) != '\\')) {
550             /* drive letter relative path; this is not allowed */
551             status = EINVAL;
552         } else {
553             /* fully qualified path; just make a copy */
554             newPath = (char *)malloc(strlen(cpath) + 1);
555             if (!newPath) {
556                 status = ENOMEM;
557             } else {
558                 (void)strcpy(newPath, cpath);
559             }
560         }
561
562     } else {
563         /* cpath has NO leading drive letter; make relative to install dir */
564         size_t pathSize = strlen(ntServerInstallDirShort) + 2;
565
566         if ((*cpath == '/') || (*cpath == '\\')) {
567             /* construct path relative to install directory only */
568             pathSize += strlen(cpath);
569
570             newPath = (char *)malloc(pathSize);
571             if (!newPath) {
572                 status = ENOMEM;
573             } else {
574                 sprintf(newPath, "%s/%s", ntServerInstallDirShort, cpath);
575             }
576         } else {
577             /* construct path relative to 'relativeTo' (and install dir) */
578             pathSize += strlen(relativeTo) + 1 + strlen(cpath);
579
580             newPath = (char *)malloc(pathSize);
581             if (!newPath) {
582                 status = ENOMEM;
583             } else {
584                 sprintf(newPath, "%s/%s/%s", ntServerInstallDirShort,
585                         relativeTo, cpath);
586             }
587         }
588     }
589
590     if (status == 0) {
591         FilepathNormalize(newPath);
592
593         /* return buffer containing fully specified path */
594         *fullPathBufp = newPath;
595     }
596
597     return status;
598 }
599
600 #else
601 /* Unix version of ConstructLocalPath() */
602
603 /*
604  * ConstructLocalPath() --  Convert a canonical (wire-format) path to a fully
605  *     specified local path.  Upon successful completion, *fullPathBufp is
606  *     set to an allocated buffer containing the fully specified local path
607  *     constructed from the cpath argument.
608  *
609  *     On Unix, path construction proceeds as follows:
610  *         1) If cpath begins with '/' then the path returned is equivalent
611  *            to cpath.
612  *         2) Otherwise the path returned is the concatenation
613  *            relativeTo + cpath.
614  *
615  *     Leading whitespace in cpath is ignored; the constructed path is
616  *     normalized (FilepathNormalize()).
617  *
618  * RETURN CODES: 0 if successful; errno code otherwise.
619  */
620 int
621 ConstructLocalPath(const char *cpath, const char *relativeTo,
622                    char **fullPathBufp)
623 {
624     int status = 0;
625     char *newPath = NULL;
626
627     if (initFlag == 0) {        /* dirpath module not yet initialized */
628 #ifdef AFS_PTHREAD_ENV
629         pthread_once(&dirInit_once, initDirPathArray);
630 #else
631         initDirPathArray();
632 #endif
633     }
634
635     *fullPathBufp = NULL;
636
637     while (isspace(*cpath)) {
638         cpath++;
639     }
640
641     LocalizePathHead(&cpath, &relativeTo);
642     if (*cpath == '/') {
643         newPath = (char *)malloc(strlen(cpath) + 1);
644         if (!newPath) {
645             status = ENOMEM;
646         } else {
647             strcpy(newPath, cpath);
648         }
649     } else {
650         newPath = (char *)malloc(strlen(relativeTo) + 1 + strlen(cpath) + 1);
651         if (!newPath) {
652             status = ENOMEM;
653         } else {
654             sprintf(newPath, "%s/%s", relativeTo, cpath);
655         }
656     }
657
658     if (status == 0) {
659         FilepathNormalize(newPath);
660
661         /* return buffer containing fully specified path */
662         *fullPathBufp = newPath;
663     }
664
665     return status;
666 }
667 #endif /* AFS_NT40_ENV */
668
669
670 /*
671  * ConstructLocalBinPath() -- A convenience wrapper for ConstructLocalPath()
672  *     that specifies the canonical AFS server binary directory as the relative
673  *     directory.
674  */
675 int
676 ConstructLocalBinPath(const char *cpath, char **fullPathBufp)
677 {
678     return ConstructLocalPath(cpath, AFSDIR_SERVER_BIN_DIRPATH,
679                               fullPathBufp);
680 }
681
682
683 /*
684  * ConstructLocalLogPath() -- A convenience wrapper for ConstructLocalPath()
685  *     that specifies the canonical AFS server logs directory as the relative
686  *     directory.
687  */
688 int
689 ConstructLocalLogPath(const char *cpath, char **fullPathBufp)
690 {
691     return ConstructLocalPath(cpath, AFSDIR_SERVER_LOGS_DIRPATH,
692                               fullPathBufp);
693 }