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 *===========================================================================*/
make_path(char path[PATH_MAX],struct inode * ino)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 *===========================================================================*/
push_path(char path[PATH_MAX],char * name)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 *===========================================================================*/
pop_path(char path[PATH_MAX])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