13
13
#include "llstdlib.h"
14
14
/* llstdlib.h pulls in standard.h, config.h, sys_inc.h */
16
19
/*********************************************
17
20
* local function prototypes
18
21
*********************************************/
22
static STRING get_user_homedir(STRING username);
19
23
static INT zero_separate_path(STRING path);
21
25
/*===========================================
44
48
/*===============================================
49
* is_path -- Is this a path (not a bare filename) ?
50
* ie, does this have any slashes in it?
51
* (does not handle escaped slashes)
52
*=============================================*/
54
is_path (CNSTRING dir)
57
if (strchr(dir,LLCHRDIRSEPARATOR)) return TRUE;
59
/* windows \ or / is path separator. */
60
if (strchr(dir,'/')) return TRUE;
61
if (dir[0] && dir[1]==':' && isasciiletter(dir[0])) {
68
/*===============================================
45
69
* is_absolute_path -- Is this an absolute path ?
46
* ie, does this begin with directory info
47
* handle WIN32 characters
70
* handle WIN32 characters, and ~ homedir references
48
71
*=============================================*/
50
73
is_absolute_path (CNSTRING dir)
52
if (is_dir_sep(dir[0]) || dir[0] == '.') return TRUE;
75
/* if it starts with a slash, it's absolute */
76
if (is_dir_sep(dir[0])) return TRUE;
77
/* if it starts with a dot, it's relative, but not relative
78
to search path, only to current directory -- as in shell logic
79
so we say it is absolute */
80
if (dir[0] == '.') return TRUE;
81
/* if it starts with ~, it is a reference to an absolute home dir */
53
82
if (dir[0] == '~') return TRUE;
55
if (is_dir_sep(dir[0])
56
|| (dir[0] && dir[1]==':' && isasciiletter(dir[0]))) {
84
/* if it starts with a drive letter, it's absolute */
85
if (dir[0] && dir[1]==':' && isasciiletter(dir[0])) {
62
92
/*=========================================
63
93
* path_match -- are paths the same ?
64
94
* handle WIN32 filename case insensitivity
76
106
* path_cmp -- compare two paths as appropriate
77
107
* handle WIN32 filename case insensitivity
78
108
*===============================*/
80
110
path_cmp (CNSTRING path1, CNSTRING path2)
82
112
/* Special case for Win32, which needs case-insensitive */
187
217
* filepath -- Find file in sequence of paths
188
218
* handles NULL in either argument
189
219
* returns alloc'd buffer
220
* Warning: if called with mode other than "r" this may not
221
* do what you want, because 1) if file is not found, it appends ext.
222
* and 2) file always goes in 1st specified directory of path unless
223
* name is absolute or ./something
190
224
*=========================================*/
192
226
filepath (CNSTRING name, CNSTRING mode, CNSTRING path, CNSTRING ext, INT utf8)
198
232
if (ISNULL(name)) return NULL;
199
233
if (ISNULL(path)) return strsave(name);
200
if (is_absolute_path(name)) return strsave(name);
201
234
nlen = strlen(name);
203
236
elen = strlen(ext);
204
237
if ((nlen > elen) && path_match(name+nlen-elen, ext)) {
205
238
/* name has an explicit extension the same as this one */
210
243
else { ext = NULL; elen = 0; }
211
244
if (nlen + strlen(path) + elen >= MAXLINELEN) return NULL;
246
/* for absolute and relative path names we first check the
247
* pathname for validity relative to the current directory
250
/* If this is a path, i.e. it has multiple path elements
251
* use the name as is first. So absolute paths don't
252
* get resolved by appending search paths.
257
if (nlen < elen || strcmp(&buf1[nlen-elen],ext) != 0) {
259
if (access(buf1, 0) == 0) return strsave(buf1);
260
buf1[nlen] = '\0'; /* remove extension */
262
if (access(buf1, 0) == 0) return strsave(buf1);
264
if (access(name, 0) == 0) return strsave(name);
266
/* fail if get here and name begins with a / or ./
267
* as we didn't find the file.
268
* however let foo/bar sneak thru, so we allow access
269
* to files in subdirectories of the search path if
270
* named in the filename.
272
if (is_dir_sep(name[0]) || (name[0] == '.' && is_dir_sep(name[1])))
273
return strsave(name);
275
if (name[0] && name[1]==':' && isasciiletter(name[0])) {
276
return strsave(name);
281
/* it is a relative path, so search for it in search path */
212
282
strcpy(buf1, path);
213
283
zero_separate_path(buf1);
227
if(access(buf2, 0) == 0) return strsave(buf2);
229
buf2[nlen-elen] = '\0'; /* remove extension */
297
if (nlen < elen || strcmp(&buf2[nlen-elen],ext) != 0) {
299
if (access(buf2, 0) == 0) return strsave(buf2);
300
buf2[nlen] = '\0'; /* remove extension */
231
303
if (access(buf2, 0) == 0) return strsave(buf2);
239
311
expand_special_fname_chars(buf2, sizeof(buf2), utf8);
241
strcpy(q, LLSTRDIRSEPARATOR);
313
if (q>buf2 && !is_dir_sep(q[-1])) {
314
strcpy(q, LLSTRDIRSEPARATOR);
244
if(ext) strcat(q, ext);
318
if (ext) strcat(q, ext);
245
319
return strsave(buf2);
247
321
/*===========================================
430
504
* path: [IN] path list to copy
431
505
* dirs: [OUT] output buffer
432
506
* NB: dirs should be one byte larger than path
507
* ignore zero length paths
433
508
*================================================*/
435
510
chop_path (CNSTRING path, STRING dirs)
484
559
expand_special_fname_chars (STRING buffer, INT buflen, INT utf8)
486
562
if (buffer[0]=='~') {
487
563
if (is_dir_sep(buffer[1])) {
488
564
STRING home = get_home();
489
565
if (home && home[0]) {
491
if ((INT)strlen(buffer)+(INT)strlen(home)+1 > buflen) {
567
if ((INT)strlen(home) + 1 + (INT)strlen(buffer) > buflen) {
494
570
tmp = strsave(buffer);
502
/* TODO: handle other homes (eg, ~someone/) ? */
578
/* check for ~name/... and resolve the ~name */
579
if ((sep = strchr(buffer,LLCHRDIRSEPARATOR))) {
580
STRING username = strsave(buffer+1);
582
username[sep-buffer+1] = 0;
583
homedir = get_user_homedir(username);
587
if ((INT)strlen(homedir) + 1 + (INT)strlen(sep+1) > buflen) {
590
tmp = strsave(sep+1);
592
llstrapps(buffer, buflen, utf8, homedir);
593
llstrapps(buffer, buflen, utf8, tmp+(sep-buffer+1));
601
/*============================================
602
* get_user_homedir -- Return home directory of specified user
603
* returns 0 if unknown or error
604
* returns alloc'd value
605
*==========================================*/
607
get_user_homedir (STRING username)
610
if (!username) return 0;
613
This could be implemented for NT+ class using NetUserGetInfo,
614
but I doubt it's worth the trouble. Perry, 2005-11-25.
616
#else /* not WIN32 */
618
/* loop through the password file/database
619
* to see if the string following ~ matches
622
while ((pw = getpwent())) {
623
if (eqstr(pw->pw_name,username)) {
624
/* found user in passwd file */
625
STRING homedir = strsave(pw->pw_dir);