static char * get_next_path_element (const char *path_list, int *path_index_pointer) { char *path; path = extract_colon_unit (path_list, path_index_pointer); if (!path) return (path); if (!*path) { free (path); path = savestring ("."); } return (path); }
/* Return the next element from PATH_LIST, a colon separated list of paths. PATH_INDEX_POINTER is the address of an index into PATH_LIST; the index is modified by this function. Return the next element of PATH_LIST or NULL if there are no more. */ char* get_next_path_element (char const* path_list, int* path_index_pointer) { char* path; path = extract_colon_unit (path_list, path_index_pointer); if (path == 0) return (path); if (*path == '\0') { free (path); path = savestring ("."); } return (path); }
/* Return the full pathname for FILENAME by searching along PATH. When found, return the stat () info for FILENAME in FINFO. If PATH is NULL, only the current directory is searched. If the file could not be found, return a NULL pointer. */ char * get_file_info_in_path (char *filename, char *path, struct stat *finfo) { char *dir; int result, index = 0; if (path == NULL) path = "."; /* Handle absolute pathnames. */ if (IS_ABSOLUTE (filename) || (*filename == '.' && (IS_SLASH (filename[1]) || (filename[1] == '.' && IS_SLASH (filename[2]))))) { if (stat (filename, finfo) == 0) return xstrdup (filename); else return NULL; } while ((dir = extract_colon_unit (path, &index))) { char *fullpath; if (!*dir) { free (dir); dir = xstrdup ("."); } fullpath = xmalloc (2 + strlen (dir) + strlen (filename)); sprintf (fullpath, "%s/%s", dir, filename); free (dir); result = stat (fullpath, finfo); if (result == 0) return fullpath; else free (fullpath); } return NULL; }
/* Scan the list of directories in PATH looking for FILENAME. If we find one that is a regular file, return it as a new string. Otherwise, return a NULL pointer. */ static char * info_file_in_path (char *filename, char *path) { struct stat finfo; char *temp_dirname; int statable, dirname_index; /* Reject ridiculous cases up front, to prevent infinite recursion later on. E.g., someone might say "info '(.)foo'"... */ if (!*filename || STREQ (filename, ".") || STREQ (filename, "..")) return NULL; dirname_index = 0; while ((temp_dirname = extract_colon_unit (path, &dirname_index))) { register int i, pre_suffix_length; char *temp; /* Expand a leading tilde if one is present. */ if (*temp_dirname == '~') { char *expanded_dirname; expanded_dirname = tilde_expand_word (temp_dirname); free (temp_dirname); temp_dirname = expanded_dirname; } temp = xmalloc (30 + strlen (temp_dirname) + strlen (filename)); strcpy (temp, temp_dirname); if (!IS_SLASH (temp[(strlen (temp)) - 1])) strcat (temp, "/"); strcat (temp, filename); pre_suffix_length = strlen (temp); free (temp_dirname); for (i = 0; info_suffixes[i]; i++) { strcpy (temp + pre_suffix_length, info_suffixes[i]); statable = (stat (temp, &finfo) == 0); /* If we have found a regular file, then use that. Else, if we have found a directory, look in that directory for this file. */ if (statable) { if (S_ISREG (finfo.st_mode)) { return temp; } else if (S_ISDIR (finfo.st_mode)) { char *newpath, *filename_only, *newtemp; newpath = xstrdup (temp); filename_only = filename_non_directory (filename); newtemp = info_file_in_path (filename_only, newpath); free (newpath); if (newtemp) { free (temp); return newtemp; } } } else { /* Add various compression suffixes to the name to see if the file is present in compressed format. */ register int j, pre_compress_suffix_length; pre_compress_suffix_length = strlen (temp); for (j = 0; compress_suffixes[j].suffix; j++) { strcpy (temp + pre_compress_suffix_length, compress_suffixes[j].suffix); statable = (stat (temp, &finfo) == 0); if (statable && (S_ISREG (finfo.st_mode))) return temp; } } } free (temp); } return NULL; }
/** * local implementation of pathfind. * @param[in] path colon separated list of directories * @param[in] fname the name we are hunting for * @param[in] mode the required file mode * @returns an allocated string with the full path, or NULL */ static char * pathfind( char const * path, char const * fname, char const * mode ) { int p_index = 0; int mode_bits = 0; char * res_path = NULL; char zPath[ AG_PATH_MAX + 1 ]; if (strchr( mode, 'r' )) mode_bits |= R_OK; if (strchr( mode, 'w' )) mode_bits |= W_OK; if (strchr( mode, 'x' )) mode_bits |= X_OK; /* * FOR each non-null entry in the colon-separated path, DO ... */ for (;;) { DIR* dirP; char* colon_unit = extract_colon_unit( zPath, path, &p_index ); if (colon_unit == NULL) break; dirP = opendir( colon_unit ); /* * IF the directory is inaccessable, THEN next directory */ if (dirP == NULL) continue; for (;;) { struct dirent *entP = readdir( dirP ); if (entP == (struct dirent*)NULL) break; /* * IF the file name matches the one we are looking for, ... */ if (strcmp(entP->d_name, fname) == 0) { char * abs_name = make_absolute(fname, colon_unit); /* * Make sure we can access it in the way we want */ if (access(abs_name, mode_bits) >= 0) { /* * We can, so normalize the name and return it below */ res_path = canonicalize_pathname(abs_name); } free(abs_name); break; } } closedir( dirP ); if (res_path != NULL) break; } return res_path; }
void maybe_build_dir_node (char *dirname) { int path_index, update_tags; char *this_dir; FILE_BUFFER *dir_buffer = info_find_file (dirname); /* If there is no "dir" in the current info path, we cannot build one from nothing. */ if (!dir_buffer) return; /* If this directory has already been built, return now. */ if (dir_buffer->flags & N_CannotGC) return; /* Initialize the list we use to avoid reading the same dir file twice with the dir file just found. */ new_dir_file_p (&dir_buffer->finfo); path_index = update_tags = 0; /* Using each element of the path, check for one of the files in DIRS_TO_ADD. Do not check for "localdir.info.Z" or anything else. Only files explictly named are eligible. This is a design decision. There can be an info file name "localdir.info" which contains information on the setting up of "localdir" files. */ while ((this_dir = extract_colon_unit (infopath, &path_index))) { register int da_index; char *from_file; /* Expand a leading tilde if one is present. */ if (*this_dir == '~') { char *tilde_expanded_dirname; tilde_expanded_dirname = tilde_expand_word (this_dir); if (tilde_expanded_dirname != this_dir) { free (this_dir); this_dir = tilde_expanded_dirname; } } /* For every different file named in DIRS_TO_ADD found in the search path, add that file's menu to our "dir" node. */ for (da_index = 0; (from_file = dirs_to_add[da_index]); da_index++) { struct stat finfo; int statable; int namelen = strlen (from_file); char *fullpath = xmalloc (3 + strlen (this_dir) + namelen); strcpy (fullpath, this_dir); if (!IS_SLASH (fullpath[strlen (fullpath) - 1])) strcat (fullpath, "/"); strcat (fullpath, from_file); statable = (stat (fullpath, &finfo) == 0); /* Only add this file if we have not seen it before. */ if (statable && S_ISREG (finfo.st_mode) && new_dir_file_p (&finfo)) { long filesize; int compressed; char *contents = filesys_read_info_file (fullpath, &filesize, &finfo, &compressed); if (contents) { update_tags++; add_menu_to_file_buffer (contents, filesize, dir_buffer); free (contents); } } free (fullpath); } free (this_dir); } if (update_tags) build_tags_and_nodes (dir_buffer); /* Flag that the dir buffer has been built. */ dir_buffer->flags |= N_CannotGC; }