X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Ffile-name.c;h=3216ef09fb98d155137510f31f683deb9152adf9;hb=f89de8c330e8f82f0e7195c4d35588cfcbdd02fc;hp=a88f83cf4da13acae2dc1f7df9d52d0b3e4dd7a8;hpb=5f168bf8465ae50ba5c2c761b52f29a0500c0658;p=pspp-builds.git diff --git a/src/data/file-name.c b/src/data/file-name.c index a88f83cf..3216ef09 100644 --- a/src/data/file-name.c +++ b/src/data/file-name.c @@ -18,19 +18,25 @@ 02110-1301, USA. */ #include -#include + #include "file-name.h" -#include -#include + #include #include -#include +#include +#include + #include "intprops.h" +#include "minmax.h" +#include "settings.h" +#include "xreadlink.h" + +#include +#include #include #include -#include "settings.h" +#include #include -#include "xreadlink.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -65,93 +71,52 @@ fn_init (void) config_path = fn_getenv_default ("STAT_CONFIG_PATH", default_config_path); } -/* Functions for performing operations on filenames. */ +/* Functions for performing operations on file names. */ -/* Substitutes $variables as defined by GETENV into TARGET. - TARGET must be a string containing the text for which substitution - is required. - Supports $var and ${var} syntaxes; - $$ substitutes as $. -*/ +/* Substitutes $variables in SRC, putting the result in DST, + properly handling the case where SRC is a substring of DST. + Variables are as defined by GETENV. Supports $var and ${var} + syntaxes; $$ substitutes as $. */ void -fn_interp_vars (struct string *target, - const char *(*getenv) (const char *)) +fn_interp_vars (struct substring src, const char *(*getenv) (const char *), + struct string *dst_) { - char *input ; - char *s ; - - assert (target); - - input = xmalloc(ds_length(target) + 1); - s = input; - - strcpy(input, ds_c_str(target)); - - if (NULL == strchr (ds_c_str(target), '$')) - goto done; - - ds_clear(target); - - for (;;) - { - switch (*s) - { - case '\0': - goto done ; - - case '$': - s++; - - if (*s == '$') - { - ds_putc (target, '$'); - s++; - } - else - { - int stop; - int start; - const char *value; - - start = ds_length (target); - - if (*s == '(') - { - stop = ')'; - s++; - } - else if (*s == '{') - { - stop = '}'; - s++; - } - else - stop = 0; - - while (*s && *s != stop - && (stop || isalpha ((unsigned char) *s))) - { - ds_putc (target, *s++); - } - - value = getenv (ds_c_str (target) + start); - ds_truncate (target, start); - ds_puts (target, value); - - if (stop && *s == stop) - s++; - } - break; - - default: - ds_putc (target, *s++); - } - } - - done: - free(input); - return; + struct string dst = DS_EMPTY_INITIALIZER; + int c; + + while ((c = ss_get_char (&src)) != EOF) + if (c != '$') + ds_put_char (&dst, c); + else + { + if (ss_match_char (&src, '$') || ss_is_empty (src)) + ds_put_char (&dst, '$'); + else + { + struct substring var_name; + size_t start; + const char *value; + + if (ss_match_char (&src, '(')) + ss_get_until (&src, ')', &var_name); + else if (ss_match_char (&src, '{')) + ss_get_until (&src, '}', &var_name); + else + ss_get_chars (&src, MIN (1, ss_span (src, ss_cstr (CC_ALNUM))), + &var_name); + + start = ds_length (&dst); + ds_put_substring (&dst, var_name); + value = getenv (ds_cstr (&dst) + start); + ds_truncate (&dst, start); + + ds_put_cstr (&dst, value); + } + } + + ds_swap (&dst, dst_); + ds_destroy (&dst); } #ifdef unix @@ -160,7 +125,7 @@ fn_interp_vars (struct string *target, char * fn_tilde_expand (const char *input) { - struct string output = DS_INITIALIZER; + struct string output = DS_EMPTY_INITIALIZER; if (input[0] == '~') { const char *home = NULL; @@ -172,11 +137,13 @@ fn_tilde_expand (const char *input) } else { - struct string user_name = DS_INITIALIZER; + struct string user_name = DS_EMPTY_INITIALIZER; struct passwd *pwd; - ds_assign_buffer (&user_name, input + 1, strcspn (input + 1, "/")); - pwd = getpwnam (ds_c_str (&user_name)); + ds_assign_substring (&user_name, + ss_buffer (input + 1, + strcspn (input + 1, "/"))); + pwd = getpwnam (ds_cstr (&user_name)); if (pwd != NULL && pwd->pw_dir[0] != '\0') { home = pwd->pw_dir; @@ -187,14 +154,14 @@ fn_tilde_expand (const char *input) if (home != NULL) { - ds_puts (&output, home); + ds_put_cstr (&output, home); if (*remainder != '\0') - ds_puts (&output, remainder); + ds_put_cstr (&output, remainder); } } if (ds_is_empty (&output)) - ds_puts (&output, input); - return ds_c_str (&output); + ds_put_cstr (&output, input); + return ds_cstr (&output); } #else /* !unix */ char * @@ -204,89 +171,91 @@ fn_tilde_expand (const char *input) } #endif /* !unix */ -/* Searches for a configuration file with name NAME in the path given - by PATH, which is tilde- and environment-interpolated. Directories - in PATH are delimited by PATH_DELIMITER, defined in . - Returns the malloc'd full name of the first file found, or NULL if - none is found. +/* Searches for a configuration file with name NAME in the path + given by PATH, which is tilde- and environment-interpolated. + Directories in PATH are delimited by ':'. Returns the + malloc'd full name of the first file found, or NULL if none is + found. - If PREFIX is non-NULL, then it is prefixed to each filename; - i.e., it looks like PREFIX/PATH_COMPONENT/NAME. This is not done - with absolute directories in the path. */ + If PREFIX is non-NULL, then it is prefixed to each file name; + i.e., it looks like PREFIX/PATH_COMPONENT/NAME. This is not + done with absolute directories in the path. */ char * fn_search_path (const char *base_name, const char *path_, const char *prefix) { struct string path; - struct string dir = DS_INITIALIZER; - struct string file = DS_INITIALIZER; + struct substring dir_; + struct string file = DS_EMPTY_INITIALIZER; size_t save_idx = 0; if (fn_is_absolute (base_name)) return fn_tilde_expand (base_name); /* Interpolate environment variables. */ - ds_create (&path, path_); - fn_interp_vars (&path, fn_getenv); + ds_init_cstr (&path, path_); + fn_interp_vars (ds_ss (&path), fn_getenv, &path); verbose_msg (2, _("searching for \"%s\" in path \"%s\""), - base_name, ds_c_str (&path)); - while (ds_separate (&path, &dir, PATH_DELIMITER_STRING, &save_idx)) + base_name, ds_cstr (&path)); + while (ds_separate (&path, ss_cstr (":"), &save_idx, &dir_)) { + struct string dir; + /* Do tilde expansion. */ + ds_init_substring (&dir, dir_); if (ds_first (&dir) == '~') { - char *tmp_str = fn_tilde_expand (ds_c_str (&dir)); - ds_assign_c_str (&dir, tmp_str); + char *tmp_str = fn_tilde_expand (ds_cstr (&dir)); + ds_assign_cstr (&dir, tmp_str); free (tmp_str); } /* Construct file name. */ ds_clear (&file); - if (prefix != NULL && !fn_is_absolute (ds_c_str (&dir))) + if (prefix != NULL && !fn_is_absolute (ds_cstr (&dir))) { - ds_puts (&file, prefix); - ds_putc (&file, DIR_SEPARATOR); + ds_put_cstr (&file, prefix); + ds_put_char (&file, '/'); } - ds_puts (&file, ds_c_str (&dir)); - if (ds_length (&dir) && ds_last (&file) != DIR_SEPARATOR) - ds_putc (&file, DIR_SEPARATOR); - ds_puts (&file, base_name); + ds_put_cstr (&file, ds_cstr (&dir)); + if (!ds_is_empty (&file) && ds_last (&file) != '/') + ds_put_char (&file, '/'); + ds_put_cstr (&file, base_name); + ds_destroy (&dir); /* Check whether file exists. */ - if (fn_exists (ds_c_str (&file))) + if (fn_exists (ds_cstr (&file))) { - verbose_msg (2, _("...found \"%s\""), ds_c_str (&file)); + verbose_msg (2, _("...found \"%s\""), ds_cstr (&file)); ds_destroy (&path); - ds_destroy (&dir); - return ds_c_str (&file); + return ds_cstr (&file); } } /* Failure. */ verbose_msg (2, _("...not found")); ds_destroy (&path); - ds_destroy (&dir); ds_destroy (&file); return NULL; } /* fn_normalize(): This very OS-dependent routine canonicalizes - filename FN1. The filename should not need to be the name of an + file name FN1. The file name should not need to be the name of an existing file. Returns a malloc()'d copy of the canonical name. This function must always succeed; if it needs to bail out then it should return xstrdup(FN1). */ #ifdef unix char * -fn_normalize (const char *filename) +fn_normalize (const char *file_name) { const char *src; char *fn1, *fn2, *dest; int maxlen; - if (fn_is_special (filename)) - return xstrdup (filename); + if (fn_is_special (file_name)) + return xstrdup (file_name); - fn1 = fn_tilde_expand (filename); + fn1 = fn_tilde_expand (file_name); /* Follow symbolic links. */ for (;;) @@ -307,7 +276,7 @@ fn_normalize (const char *filename) dest = fn2 = xmalloc (maxlen + 1); src = fn1; - if (*src == DIR_SEPARATOR) + if (*src == '/') *dest++ = *src++; else { @@ -332,8 +301,8 @@ fn_normalize (const char *filename) fn2 = xrealloc (fn2, maxlen + 1); dest = fn2 + ofs; } - if (dest[-1] != DIR_SEPARATOR) - *dest++ = DIR_SEPARATOR; + if (dest[-1] != '/') + *dest++ = '/'; } for (;;) @@ -343,25 +312,25 @@ fn_normalize (const char *filename) c = *src++; f = 0; - if (c == DIR_SEPARATOR || c == 0) + if (c == '/' || c == 0) { /* remove `./', `../' from directory */ - if (dest[-1] == '.' && dest[-2] == DIR_SEPARATOR) + if (dest[-1] == '.' && dest[-2] == '/') dest--; - else if (dest[-1] == '.' && dest[-2] == '.' && dest[-3] == DIR_SEPARATOR) + else if (dest[-1] == '.' && dest[-2] == '.' && dest[-3] == '/') { dest -= 3; if (dest == fn2) dest++; - while (dest[-1] != DIR_SEPARATOR) + while (dest[-1] != '/') dest--; } - else if (dest[-1] != DIR_SEPARATOR) /* remove extra slashes */ + else if (dest[-1] != '/') /* remove extra slashes */ f = 1; if (c == 0) { - if (dest[-1] == DIR_SEPARATOR && dest > fn2 + 1) + if (dest[-1] == '/' && dest > fn2 + 1) dest--; *dest = 0; free (fn1); @@ -393,9 +362,9 @@ fn_normalize (const char *fn1) DWORD success; char *fn2; - /* Don't change special filenames. */ - if (is_special_filename (filename)) - return xstrdup (filename); + /* Don't change special file names. */ + if (is_special_file_name (file_name)) + return xstrdup (file_name); /* First find the required buffer length. */ len = GetFullPathName (fn1, 0, NULL, NULL); @@ -447,39 +416,39 @@ fn_normalize (const char *fn) } #endif /* not Lose32, Unix, or DJGPP */ -/* Returns the directory part of FILENAME, as a malloc()'d +/* Returns the directory part of FILE_NAME, as a malloc()'d string. */ char * -fn_dir_name (const char *filename) +fn_dir_name (const char *file_name) { const char *p; char *s; size_t len; - len = strlen (filename); - if (len == 1 && filename[0] == '/') - p = filename + 1; - else if (len && filename[len - 1] == DIR_SEPARATOR) - p = buf_find_reverse (filename, len - 1, filename + len - 1, 1); + len = strlen (file_name); + if (len == 1 && file_name[0] == '/') + p = file_name + 1; + else if (len && file_name[len - 1] == '/') + p = buf_find_reverse (file_name, len - 1, file_name + len - 1, 1); else - p = strrchr (filename, DIR_SEPARATOR); + p = strrchr (file_name, '/'); if (p == NULL) - p = filename; + p = file_name; - s = xmalloc (p - filename + 1); - memcpy (s, filename, p - filename); - s[p - filename] = 0; + s = xmalloc (p - file_name + 1); + memcpy (s, file_name, p - file_name); + s[p - file_name] = 0; return s; } -/* Returns the extension part of FILENAME as a malloc()'d string. - If FILENAME does not have an extension, returns an empty +/* Returns the extension part of FILE_NAME as a malloc()'d string. + If FILE_NAME does not have an extension, returns an empty string. */ char * -fn_extension (const char *filename) +fn_extension (const char *file_name) { - const char *extension = strrchr (filename, '.'); + const char *extension = strrchr (file_name, '.'); if (extension == NULL) extension = ""; return xstrdup (extension); @@ -524,8 +493,8 @@ fn_get_cwd (void) /* Find out information about files. */ -/* Returns nonzero iff NAME specifies an absolute filename. */ -int +/* Returns true iff NAME specifies an absolute file name. */ +bool fn_is_absolute (const char *name) { #ifdef unix @@ -533,37 +502,37 @@ fn_is_absolute (const char *name) || !strncmp (name, "./", 2) || !strncmp (name, "../", 3) || name[0] == '~') - return 1; + return true; #elif defined (__MSDOS__) if (name[0] == '\\' || !strncmp (name, ".\\", 2) || !strncmp (name, "..\\", 3) || (name[0] && name[1] == ':')) - return 1; + return true; #endif - return 0; + return false; } -/* Returns 1 if the filename specified is a virtual file that doesn't - really exist on disk, 0 if it's a real filename. */ -int -fn_is_special (const char *filename) +/* Returns true if FILE_NAME is a virtual file that doesn't + really exist on disk, false if it's a real file name. */ +bool +fn_is_special (const char *file_name) { - if (!strcmp (filename, "-") || !strcmp (filename, "stdin") - || !strcmp (filename, "stdout") || !strcmp (filename, "stderr") + if (!strcmp (file_name, "-") || !strcmp (file_name, "stdin") + || !strcmp (file_name, "stdout") || !strcmp (file_name, "stderr") #ifdef unix - || filename[0] == '|' - || (*filename && filename[strlen (filename) - 1] == '|') + || file_name[0] == '|' + || (*file_name && file_name[strlen (file_name) - 1] == '|') #endif ) - return 1; + return true; - return 0; + return false; } -/* Returns nonzero if file with name NAME exists. */ -int +/* Returns true if file with name NAME exists. */ +bool fn_exists (const char *name) { #ifdef unix @@ -573,18 +542,18 @@ fn_exists (const char *name) #else FILE *f = fopen (name, "r"); if (!f) - return 0; + return false; fclose (f); - return 1; + return true; #endif } -/* Returns the symbolic link value for FILENAME as a dynamically +/* Returns the symbolic link value for FILE_NAME as a dynamically allocated buffer, or a null pointer on failure. */ char * -fn_readlink (const char *filename) +fn_readlink (const char *file_name) { - return xreadlink (filename, 32); + return xreadlink (file_name, 32); } /* Environment variables. */ @@ -714,11 +683,11 @@ struct file_identity caller is responsible for freeing the structure with fn_free_identity() when finished. */ struct file_identity * -fn_get_identity (const char *filename) +fn_get_identity (const char *file_name) { struct stat s; - if (stat (filename, &s) == 0) + if (stat (file_name, &s) == 0) { struct file_identity *identity = xmalloc (sizeof *identity); identity->device = s.st_dev; @@ -752,7 +721,7 @@ fn_compare_file_identities (const struct file_identity *a, /* A file's identity. */ struct file_identity { - char *normalized_filename; /* File's normalized name. */ + char *normalized_file_name; /* File's normalized name. */ }; /* Returns a pointer to a dynamically allocated structure whose @@ -762,10 +731,10 @@ struct file_identity caller is responsible for freeing the structure with fn_free_identity() when finished. */ struct file_identity * -fn_get_identity (const char *filename) +fn_get_identity (const char *file_name) { struct file_identity *identity = xmalloc (sizeof *identity); - identity->normalized_filename = fn_normalize (filename); + identity->normalized_file_name = fn_normalize (file_name); return identity; } @@ -775,7 +744,7 @@ fn_free_identity (struct file_identity *identity) { if (identity != NULL) { - free (identity->normalized_filename); + free (identity->normalized_file_name); free (identity); } } @@ -785,6 +754,6 @@ int fn_compare_file_identities (const struct file_identity *a, const struct file_identity *b) { - return strcmp (a->normalized_filename, b->normalized_filename); + return strcmp (a->normalized_file_name, b->normalized_file_name); } #endif /* not unix */