1 /* This file contains routines for creating and manipulating path strings. 2 * 3 * The entry points into this file are: 4 * make_path construct a path string for an inode 5 * push_path add a path component to the end of a path string 6 * pop_path remove the last path component from a path string 7 * 8 * Created: 9 * April 2009 (D.C. van Moolenbroek) 10 */ 11 12 #include "inc.h" 13 14 /*===========================================================================* 15 * make_path * 16 *===========================================================================*/ 17 int make_path(char path[PATH_MAX], struct inode *ino) 18 { 19 /* Given an inode, construct the path identifying that inode. 20 */ 21 char buf[PATH_MAX], *p, *prefix; 22 size_t len, plen, total; 23 24 p = &buf[sizeof(buf) - 1]; 25 p[0] = 0; 26 27 dprintf(("%s: make_path: constructing path for inode %d\n", 28 sffs_name, ino->i_num)); 29 30 /* Get the length of the prefix, skipping any leading slashes. */ 31 for (prefix = sffs_params->p_prefix; prefix[0] == '/'; prefix++); 32 plen = strlen(prefix); 33 34 /* Construct the path right-to-left in a temporary buffer first. */ 35 for (total = plen; ino != NULL && !IS_ROOT(ino); ino = ino->i_parent) { 36 len = strlen(ino->i_name); 37 38 total += len + 1; 39 p -= len + 1; 40 41 if (total >= sizeof(buf)) 42 return ENAMETOOLONG; 43 44 p[0] = '/'; 45 memcpy(p + 1, ino->i_name, len); 46 } 47 48 /* If any of the intermediate inodes has no parent, the final inode is no 49 * longer addressable by name. 50 */ 51 if (ino == NULL) 52 return ENOENT; 53 54 /* Put the result in the actual buffer. We need the leading slash in the 55 * temporary buffer only when the prefix is not empty. 56 */ 57 if (!prefix[0] && p[0] == '/') p++; 58 59 strlcpy(path, prefix, PATH_MAX); 60 strlcpy(&path[plen], p, PATH_MAX - plen); 61 62 dprintf(("%s: make_path: resulting path is '%s'\n", sffs_name, path)); 63 64 return OK; 65 } 66 67 /*===========================================================================* 68 * push_path * 69 *===========================================================================*/ 70 int push_path(char path[PATH_MAX], char *name) 71 { 72 /* Add a component to the end of a path. 73 */ 74 size_t len, add; 75 76 len = strlen(path); 77 add = strlen(name); 78 if (len > 0) add++; 79 80 if (len + add >= PATH_MAX) 81 return ENAMETOOLONG; 82 83 if (len > 0) path[len++] = '/'; 84 strlcpy(&path[len], name, PATH_MAX - len); 85 86 return OK; 87 } 88 89 /*===========================================================================* 90 * pop_path * 91 *===========================================================================*/ 92 void pop_path(char path[PATH_MAX]) 93 { 94 /* Remove the last component from a path. 95 */ 96 char *p; 97 98 p = strrchr(path, '/'); 99 100 if (p == NULL) { 101 p = path; 102 103 /* Can't pop the root component */ 104 assert(p[0] != 0); 105 } 106 107 p[0] = 0; 108 } 109