114 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			114 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(path, ino)
 | 
						|
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(path, name)
 | 
						|
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(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;
 | 
						|
}
 |