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