summaryrefslogtreecommitdiff
path: root/minix/lib/libsffs/path.c
blob: 512230f68ea24f1d699b8db2949671125fddb9f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* 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;
}