summaryrefslogtreecommitdiff
path: root/minix/lib/libsffs/verify.c
blob: d335ebd939c96f46eb23db177d65a8f19f4d5c09 (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
109
110
111
112
113
114
115
116
117
118
/* This file contains routines that verify inodes and paths against the host.
 *
 * The entry points into this file are:
 *   verify_path	check whether a path,inode pair is still valid
 *   verify_inode	construct a path for an inode and verify the inode
 *   verify_dentry	check a directory inode and look for a directory entry
 *
 * Created:
 *   April 2009 (D.C. van Moolenbroek)
 */

#include "inc.h"

/*===========================================================================*
 *				verify_path				     *
 *===========================================================================*/
int verify_path(char path[PATH_MAX], struct inode *ino,
	struct sffs_attr *attr, int *stale)
{
/* Given a path, and the inode associated with that path, verify if the inode
 * still matches the real world. Obtain the attributes of the file identified
 * by the given path, and see if they match. If not, possibly mark the inode
 * as deleted and return an error. Only upon success is the inode guaranteed
 * to be usable.
 *
 * The caller must set the a_mask field of the passed attr struct.
 * If 'stale' is not NULL, the value it points to must be initialized to 0,
 * and will be set to 1 if the path was valid but the inode wasn't.
 */
  int r;

  attr->a_mask |= SFFS_ATTR_MODE;

  r = sffs_table->t_getattr(path, attr);

  dprintf(("%s: verify_path: getattr('%s') returned %d\n",
	sffs_name, path, r));

  if (r != OK) {
	/* If we are told that the path does not exist, delete the inode */
	if (r == ENOENT || r == ENOTDIR)
		del_dentry(ino);

	return r; /* path isn't valid */
  }

  /* If the file type (reg, dir) isn't what we thought, delete the inode */
  if ((ino->i_flags & I_DIR) != MODE_TO_DIRFLAG(attr->a_mode)) {
	del_dentry(ino);

	if (stale != NULL) *stale = 1;
	return ENOENT; /* path is valid, inode wasn't */
  }

  return OK; /* path and inode are valid */
}

/*===========================================================================*
 *				verify_inode				     *
 *===========================================================================*/
int verify_inode(
	struct inode *ino,    	/* inode to verify */
	char path[PATH_MAX],  	/* buffer in which to store the path */
	struct sffs_attr *attr	/* buffer for attributes, or NULL */
)
{
/* Given an inode, construct a path identifying the inode, and check whether
 * that path is still valid for that inode (as far as we can tell). As a side
 * effect, store attributes in the given attribute structure if not NULL (its
 * a_mask member must then be set).
 */
  struct sffs_attr attr2;
  int r;

  if ((r = make_path(path, ino)) != OK) return r;

  if (attr == NULL) {
	attr2.a_mask = 0;

	attr = &attr2;
  }

  return verify_path(path, ino, attr, NULL);
}

/*===========================================================================*
 *				verify_dentry				     *
 *===========================================================================*/
int verify_dentry(
	struct inode *parent, 	/* parent inode: the inode to verify */
	char name[NAME_MAX+1],	/* the given directory entry path component */
	char path[PATH_MAX],  	/* buffer to store the resulting path in */
	struct inode **res_ino	/* pointer for addressed inode (or NULL) */
)
{
/* Given a directory inode and a name, construct a path identifying that
 * directory entry, check whether the path to the parent is still valid, and
 * check whether there is an inode pointed to by the full path. Upon success,
 * res_ino will contain either the inode for the full path, with increased
 * refcount, or NULL if no such inode exists.
 */
  int r;

  if ((r = verify_inode(parent, path, NULL)) != OK)
	return r;

  dprintf(("%s: verify_dentry: given path is '%s', name '%s'\n",
	sffs_name, path, name));

  if ((r = push_path(path, name)) != OK)
	return r;

  dprintf(("%s: verify_dentry: path now '%s'\n", sffs_name, path));

  *res_ino = lookup_dentry(parent, name);

  return OK;
}