xref: /minix3/minix/lib/libsffs/path.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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