109 lines
2.7 KiB
C
109 lines
2.7 KiB
C
|
/* This file contains routines for creating and manipulating path strings.
|
||
|
*
|
||
|
* The entry points into this file are:
|
||
|
* make_path construct a path string for an inode
|
||
|
* push_path add a path component to the end of a path string
|
||
|
* pop_path remove the last path component from a path string
|
||
|
*
|
||
|
* Created:
|
||
|
* April 2009 (D.C. van Moolenbroek)
|
||
|
*/
|
||
|
|
||
|
#include "inc.h"
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* make_path *
|
||
|
*===========================================================================*/
|
||
|
int make_path(char path[PATH_MAX], struct inode *ino)
|
||
|
{
|
||
|
/* Given an inode, construct the path identifying that inode.
|
||
|
*/
|
||
|
char buf[PATH_MAX], *p, *prefix;
|
||
|
size_t len, plen, total;
|
||
|
|
||
|
p = &buf[sizeof(buf) - 1];
|
||
|
p[0] = 0;
|
||
|
|
||
|
dprintf(("%s: make_path: constructing path for inode %d\n",
|
||
|
sffs_name, ino->i_num));
|
||
|
|
||
|
/* Get the length of the prefix, skipping any leading slashes. */
|
||
|
for (prefix = sffs_params->p_prefix; prefix[0] == '/'; prefix++);
|
||
|
plen = strlen(prefix);
|
||
|
|
||
|
/* Construct the path right-to-left in a temporary buffer first. */
|
||
|
for (total = plen; ino != NULL && !IS_ROOT(ino); ino = ino->i_parent) {
|
||
|
len = strlen(ino->i_name);
|
||
|
|
||
|
total += len + 1;
|
||
|
p -= len + 1;
|
||
|
|
||
|
if (total >= sizeof(buf))
|
||
|
return ENAMETOOLONG;
|
||
|
|
||
|
p[0] = '/';
|
||
|
memcpy(p + 1, ino->i_name, len);
|
||
|
}
|
||
|
|
||
|
/* If any of the intermediate inodes has no parent, the final inode is no
|
||
|
* longer addressable by name.
|
||
|
*/
|
||
|
if (ino == NULL)
|
||
|
return ENOENT;
|
||
|
|
||
|
/* Put the result in the actual buffer. We need the leading slash in the
|
||
|
* temporary buffer only when the prefix is not empty.
|
||
|
*/
|
||
|
if (!prefix[0] && p[0] == '/') p++;
|
||
|
|
||
|
strlcpy(path, prefix, PATH_MAX);
|
||
|
strlcpy(&path[plen], p, PATH_MAX - plen);
|
||
|
|
||
|
dprintf(("%s: make_path: resulting path is '%s'\n", sffs_name, path));
|
||
|
|
||
|
return OK;
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* push_path *
|
||
|
*===========================================================================*/
|
||
|
int push_path(char path[PATH_MAX], char *name)
|
||
|
{
|
||
|
/* Add a component to the end of a path.
|
||
|
*/
|
||
|
size_t len, add;
|
||
|
|
||
|
len = strlen(path);
|
||
|
add = strlen(name);
|
||
|
if (len > 0) add++;
|
||
|
|
||
|
if (len + add >= PATH_MAX)
|
||
|
return ENAMETOOLONG;
|
||
|
|
||
|
if (len > 0) path[len++] = '/';
|
||
|
strlcpy(&path[len], name, PATH_MAX - len);
|
||
|
|
||
|
return OK;
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* pop_path *
|
||
|
*===========================================================================*/
|
||
|
void pop_path(char path[PATH_MAX])
|
||
|
{
|
||
|
/* Remove the last component from a path.
|
||
|
*/
|
||
|
char *p;
|
||
|
|
||
|
p = strrchr(path, '/');
|
||
|
|
||
|
if (p == NULL) {
|
||
|
p = path;
|
||
|
|
||
|
/* Can't pop the root component */
|
||
|
assert(p[0] != 0);
|
||
|
}
|
||
|
|
||
|
p[0] = 0;
|
||
|
}
|