xref: /minix3/minix/fs/procfs/tree.c (revision 305e366fe47197851cc728bd12ee4d4f1d8f7d64)
1f1abbce7SDavid van Moolenbroek /* ProcFS - tree.c - dynamic PID tree management and hook implementations */
2433d6423SLionel Sambuc 
3433d6423SLionel Sambuc #include "inc.h"
4433d6423SLionel Sambuc 
5*305e366fSDavid van Moolenbroek struct minix_proc_list proc_list[NR_PROCS];
6433d6423SLionel Sambuc 
7433d6423SLionel Sambuc static int nr_pid_entries;
8433d6423SLionel Sambuc 
9f1abbce7SDavid van Moolenbroek /*
10*305e366fSDavid van Moolenbroek  * Return a PID for the given slot, or 0 if the slot is not in use.
11433d6423SLionel Sambuc  */
12*305e366fSDavid van Moolenbroek pid_t
pid_from_slot(int slot)13*305e366fSDavid van Moolenbroek pid_from_slot(int slot)
14f1abbce7SDavid van Moolenbroek {
15433d6423SLionel Sambuc 
16*305e366fSDavid van Moolenbroek 	/* All kernel tasks are always present.*/
17433d6423SLionel Sambuc 	if (slot < NR_TASKS)
18*305e366fSDavid van Moolenbroek 		return (pid_t)(slot - NR_TASKS);
19433d6423SLionel Sambuc 
20*305e366fSDavid van Moolenbroek 	/* For regular processes, check the process list. */
21*305e366fSDavid van Moolenbroek 	if (proc_list[slot - NR_TASKS].mpl_flags & MPLF_IN_USE)
22*305e366fSDavid van Moolenbroek 		return proc_list[slot - NR_TASKS].mpl_pid;
23*305e366fSDavid van Moolenbroek 	else
24*305e366fSDavid van Moolenbroek 		return 0;
25*305e366fSDavid van Moolenbroek 
26433d6423SLionel Sambuc }
27433d6423SLionel Sambuc 
28f1abbce7SDavid van Moolenbroek /*
29f1abbce7SDavid van Moolenbroek  * Check if the owner user and group ID of the inode are still in sync with
30433d6423SLionel Sambuc  * the current effective user and group ID of the given process.
31433d6423SLionel Sambuc  */
32f1abbce7SDavid van Moolenbroek static int
check_owner(struct inode * node,int slot)33f1abbce7SDavid van Moolenbroek check_owner(struct inode * node, int slot)
34f1abbce7SDavid van Moolenbroek {
35433d6423SLionel Sambuc 	struct inode_stat stat;
36433d6423SLionel Sambuc 
37433d6423SLionel Sambuc 	if (slot < NR_TASKS) return TRUE;
38433d6423SLionel Sambuc 
39433d6423SLionel Sambuc 	get_inode_stat(node, &stat);
40433d6423SLionel Sambuc 
41*305e366fSDavid van Moolenbroek 	return (stat.uid == proc_list[slot - NR_TASKS].mpl_uid &&
42*305e366fSDavid van Moolenbroek 	    stat.gid == proc_list[slot - NR_TASKS].mpl_gid);
43433d6423SLionel Sambuc }
44433d6423SLionel Sambuc 
45f1abbce7SDavid van Moolenbroek /*
46f1abbce7SDavid van Moolenbroek  * Fill in an inode_stat structure for the given process slot and per-PID file
47f1abbce7SDavid van Moolenbroek  * index (or NO_INDEX for the process subdirectory root).
48433d6423SLionel Sambuc  */
49f1abbce7SDavid van Moolenbroek static void
make_stat(struct inode_stat * stat,int slot,int index)50f1abbce7SDavid van Moolenbroek make_stat(struct inode_stat * stat, int slot, int index)
51f1abbce7SDavid van Moolenbroek {
52433d6423SLionel Sambuc 
53433d6423SLionel Sambuc 	if (index == NO_INDEX)
54433d6423SLionel Sambuc 		stat->mode = DIR_ALL_MODE;
55433d6423SLionel Sambuc 	else
56433d6423SLionel Sambuc 		stat->mode = pid_files[index].mode;
57433d6423SLionel Sambuc 
58433d6423SLionel Sambuc 	if (slot < NR_TASKS) {
59433d6423SLionel Sambuc 		stat->uid = SUPER_USER;
60433d6423SLionel Sambuc 		stat->gid = SUPER_USER;
61433d6423SLionel Sambuc 	} else {
62*305e366fSDavid van Moolenbroek 		stat->uid = proc_list[slot - NR_TASKS].mpl_uid;
63*305e366fSDavid van Moolenbroek 		stat->gid = proc_list[slot - NR_TASKS].mpl_gid;
64433d6423SLionel Sambuc 	}
65433d6423SLionel Sambuc 
66433d6423SLionel Sambuc 	stat->size = 0;
67433d6423SLionel Sambuc 	stat->dev = NO_DEV;
68433d6423SLionel Sambuc }
69433d6423SLionel Sambuc 
70f1abbce7SDavid van Moolenbroek /*
71f1abbce7SDavid van Moolenbroek  * Return whether the given node is a PID directory.
72433d6423SLionel Sambuc  */
73f1abbce7SDavid van Moolenbroek static int
dir_is_pid(struct inode * node)74f1abbce7SDavid van Moolenbroek dir_is_pid(struct inode *node)
75f1abbce7SDavid van Moolenbroek {
76433d6423SLionel Sambuc 
77433d6423SLionel Sambuc 	return (get_parent_inode(node) == get_root_inode() &&
78433d6423SLionel Sambuc 	    get_inode_index(node) != NO_INDEX);
79433d6423SLionel Sambuc }
80433d6423SLionel Sambuc 
81f1abbce7SDavid van Moolenbroek /*
82*305e366fSDavid van Moolenbroek  * Get the process listing from the MIB service.
83433d6423SLionel Sambuc  */
84f1abbce7SDavid van Moolenbroek static int
update_list(void)85*305e366fSDavid van Moolenbroek update_list(void)
86f1abbce7SDavid van Moolenbroek {
87*305e366fSDavid van Moolenbroek 	const int mib[] = { CTL_MINIX, MINIX_PROC, PROC_LIST };
88*305e366fSDavid van Moolenbroek 	size_t size;
89433d6423SLionel Sambuc 	int r;
90433d6423SLionel Sambuc 
91*305e366fSDavid van Moolenbroek 	size = sizeof(proc_list);
92*305e366fSDavid van Moolenbroek 	if (__sysctl(mib, __arraycount(mib), proc_list, &size, NULL, 0) != 0)
93*305e366fSDavid van Moolenbroek 		printf("ProcFS: unable to obtain process list (%d)\n", -errno);
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc 	return OK;
96433d6423SLionel Sambuc }
97433d6423SLionel Sambuc 
98f1abbce7SDavid van Moolenbroek /*
99f1abbce7SDavid van Moolenbroek  * Initialize this module, before VTreeFS is started.  As part of the process,
100f1abbce7SDavid van Moolenbroek  * check if we're not compiled against a kernel different from the one that is
101f1abbce7SDavid van Moolenbroek  * running at the moment.
102433d6423SLionel Sambuc  */
103f1abbce7SDavid van Moolenbroek int
init_tree(void)104f1abbce7SDavid van Moolenbroek init_tree(void)
105f1abbce7SDavid van Moolenbroek {
106433d6423SLionel Sambuc 	int i, r;
107433d6423SLionel Sambuc 
108*305e366fSDavid van Moolenbroek 	if ((r = update_list()) != OK)
109433d6423SLionel Sambuc 		return r;
110433d6423SLionel Sambuc 
111f1abbce7SDavid van Moolenbroek 	/*
112f1abbce7SDavid van Moolenbroek 	 * Get the maximum number of entries that we may add to each PID's
113433d6423SLionel Sambuc 	 * directory.  We could just default to a large value, but why not get
114433d6423SLionel Sambuc 	 * it right?
115433d6423SLionel Sambuc 	 */
116433d6423SLionel Sambuc 	for (i = 0; pid_files[i].name != NULL; i++);
117433d6423SLionel Sambuc 
118433d6423SLionel Sambuc 	nr_pid_entries = i;
119433d6423SLionel Sambuc 
120433d6423SLionel Sambuc 	return OK;
121433d6423SLionel Sambuc }
122433d6423SLionel Sambuc 
123f1abbce7SDavid van Moolenbroek /*
124f1abbce7SDavid van Moolenbroek  * Out of inodes - the NR_INODES value is set too low.  We can not do much, but
125f1abbce7SDavid van Moolenbroek  * we might be able to continue with degraded functionality, so do not panic.
126f1abbce7SDavid van Moolenbroek  * If the NR_INODES value is not below the *crucial* minimum, the symptom of
127f1abbce7SDavid van Moolenbroek  * this case will be an incomplete listing of the main proc directory.
128433d6423SLionel Sambuc  */
12931b6611aSDavid van Moolenbroek void
out_of_inodes(void)130f1abbce7SDavid van Moolenbroek out_of_inodes(void)
131f1abbce7SDavid van Moolenbroek {
132433d6423SLionel Sambuc 	static int warned = FALSE;
133433d6423SLionel Sambuc 
134433d6423SLionel Sambuc 	if (warned == FALSE) {
135433d6423SLionel Sambuc 		printf("PROCFS: out of inodes!\n");
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc 		warned = TRUE;
138433d6423SLionel Sambuc 	}
139433d6423SLionel Sambuc }
140433d6423SLionel Sambuc 
141f1abbce7SDavid van Moolenbroek /*
142f1abbce7SDavid van Moolenbroek  * Regenerate the set of PID directories in the root directory of the file
143f1abbce7SDavid van Moolenbroek  * system.  Add new directories and delete old directories as appropriate;
144f1abbce7SDavid van Moolenbroek  * leave unchanged those that should remain the same.
145f1abbce7SDavid van Moolenbroek  */
146f1abbce7SDavid van Moolenbroek static void
construct_pid_dirs(void)147f1abbce7SDavid van Moolenbroek construct_pid_dirs(void)
148433d6423SLionel Sambuc {
149f1abbce7SDavid van Moolenbroek 	/*
150433d6423SLionel Sambuc 	 * We have to make two passes.  Otherwise, we would trigger a vtreefs
151433d6423SLionel Sambuc 	 * assert when we add an entry for a PID before deleting the previous
152433d6423SLionel Sambuc 	 * entry for that PID.  While rare, such rapid PID reuse does occur in
153433d6423SLionel Sambuc 	 * practice.
154433d6423SLionel Sambuc 	 */
155433d6423SLionel Sambuc 	struct inode *root, *node;
156433d6423SLionel Sambuc 	struct inode_stat stat;
157433d6423SLionel Sambuc 	char name[PNAME_MAX+1];
158433d6423SLionel Sambuc 	pid_t pid;
159433d6423SLionel Sambuc 	int i;
160433d6423SLionel Sambuc 
161433d6423SLionel Sambuc 	root = get_root_inode();
162433d6423SLionel Sambuc 
163433d6423SLionel Sambuc 	/* First pass: delete old entries. */
164433d6423SLionel Sambuc 	for (i = 0; i < NR_PROCS + NR_TASKS; i++) {
165433d6423SLionel Sambuc 		/* Do we already have an inode associated with this slot? */
166433d6423SLionel Sambuc 		node = get_inode_by_index(root, i);
167433d6423SLionel Sambuc 		if (node == NULL)
168433d6423SLionel Sambuc 			continue;
169433d6423SLionel Sambuc 
170f1abbce7SDavid van Moolenbroek 		/*
171f1abbce7SDavid van Moolenbroek 		 * If the process slot is not in use, delete the associated
172*305e366fSDavid van Moolenbroek 		 * inode.  Otherwise, get the process ID.
173433d6423SLionel Sambuc 		 */
174*305e366fSDavid van Moolenbroek 		if ((pid = pid_from_slot(i)) == 0) {
175433d6423SLionel Sambuc 			delete_inode(node);
176433d6423SLionel Sambuc 
177433d6423SLionel Sambuc 			continue;
178433d6423SLionel Sambuc 		}
179433d6423SLionel Sambuc 
180f1abbce7SDavid van Moolenbroek 		/*
181f1abbce7SDavid van Moolenbroek 		 * If there is an old entry, see if the pid matches the current
182433d6423SLionel Sambuc 		 * entry, and the owner is still the same.  Otherwise, delete
183433d6423SLionel Sambuc 		 * the old entry first.  We reconstruct the entire subtree even
184433d6423SLionel Sambuc 		 * if only the owner changed, for security reasons: if a
185433d6423SLionel Sambuc 		 * process could keep open a file or directory across the owner
186433d6423SLionel Sambuc 		 * change, it might be able to access information it shouldn't.
187433d6423SLionel Sambuc 		 */
188433d6423SLionel Sambuc 		if (pid != (pid_t)get_inode_cbdata(node) ||
189433d6423SLionel Sambuc 		    !check_owner(node, i))
190433d6423SLionel Sambuc 			delete_inode(node);
191433d6423SLionel Sambuc 	}
192433d6423SLionel Sambuc 
193433d6423SLionel Sambuc 	/* Second pass: add new entries. */
194433d6423SLionel Sambuc 	for (i = 0; i < NR_PROCS + NR_TASKS; i++) {
195433d6423SLionel Sambuc 		/* If the process slot is not in use, skip this slot. */
196*305e366fSDavid van Moolenbroek 		if ((pid = pid_from_slot(i)) == 0)
197433d6423SLionel Sambuc 			continue;
198433d6423SLionel Sambuc 
199f1abbce7SDavid van Moolenbroek 		/*
200f1abbce7SDavid van Moolenbroek 		 * If we have an inode associated with this slot, we have
201433d6423SLionel Sambuc 		 * already checked it to be up-to-date above.
202433d6423SLionel Sambuc 		 */
203433d6423SLionel Sambuc 		if (get_inode_by_index(root, i) != NULL)
204433d6423SLionel Sambuc 			continue;
205433d6423SLionel Sambuc 
206433d6423SLionel Sambuc 		/* Get the process ID. */
207433d6423SLionel Sambuc 		if (i < NR_TASKS)
208433d6423SLionel Sambuc 			pid = (pid_t)(i - NR_TASKS);
209433d6423SLionel Sambuc 		else
210*305e366fSDavid van Moolenbroek 			pid = proc_list[i - NR_TASKS].mpl_pid;
211433d6423SLionel Sambuc 
212433d6423SLionel Sambuc 		/* Add the entry for the process slot. */
213433d6423SLionel Sambuc 		snprintf(name, PNAME_MAX + 1, "%d", pid);
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc 		make_stat(&stat, i, NO_INDEX);
216433d6423SLionel Sambuc 
217433d6423SLionel Sambuc 		node = add_inode(root, name, i, &stat, nr_pid_entries,
218433d6423SLionel Sambuc 		    (cbdata_t)pid);
219433d6423SLionel Sambuc 
220433d6423SLionel Sambuc 		if (node == NULL)
221433d6423SLionel Sambuc 			out_of_inodes();
222433d6423SLionel Sambuc 	}
223433d6423SLionel Sambuc }
224433d6423SLionel Sambuc 
225f1abbce7SDavid van Moolenbroek /*
226f1abbce7SDavid van Moolenbroek  * Construct one file in a PID directory, if a file with the given name should
227f1abbce7SDavid van Moolenbroek  * exist at all.
228433d6423SLionel Sambuc  */
229f1abbce7SDavid van Moolenbroek static void
make_one_pid_entry(struct inode * parent,char * name,int slot)230f1abbce7SDavid van Moolenbroek make_one_pid_entry(struct inode * parent, char * name, int slot)
231f1abbce7SDavid van Moolenbroek {
232433d6423SLionel Sambuc 	struct inode *node;
233433d6423SLionel Sambuc 	struct inode_stat stat;
234433d6423SLionel Sambuc 	int i;
235433d6423SLionel Sambuc 
236433d6423SLionel Sambuc 	/* Don't readd if it is already there. */
237433d6423SLionel Sambuc 	node = get_inode_by_name(parent, name);
238433d6423SLionel Sambuc 	if (node != NULL)
239433d6423SLionel Sambuc 		return;
240433d6423SLionel Sambuc 
241433d6423SLionel Sambuc 	/* Only add the file if it is a known, registered name. */
242433d6423SLionel Sambuc 	for (i = 0; pid_files[i].name != NULL; i++) {
243433d6423SLionel Sambuc 		if (!strcmp(name, pid_files[i].name)) {
244433d6423SLionel Sambuc 			make_stat(&stat, slot, i);
245433d6423SLionel Sambuc 
246f1abbce7SDavid van Moolenbroek 			node = add_inode(parent, name, i, &stat, (index_t)0,
247f1abbce7SDavid van Moolenbroek 			    (cbdata_t)0);
248433d6423SLionel Sambuc 
249433d6423SLionel Sambuc 			if (node == NULL)
250433d6423SLionel Sambuc 				out_of_inodes();
251433d6423SLionel Sambuc 
252433d6423SLionel Sambuc 			break;
253433d6423SLionel Sambuc 		}
254433d6423SLionel Sambuc 	}
255433d6423SLionel Sambuc }
256433d6423SLionel Sambuc 
257f1abbce7SDavid van Moolenbroek /*
258f1abbce7SDavid van Moolenbroek  * Construct all files in a PID directory.
259433d6423SLionel Sambuc  */
260f1abbce7SDavid van Moolenbroek static void
make_all_pid_entries(struct inode * parent,int slot)261f1abbce7SDavid van Moolenbroek make_all_pid_entries(struct inode * parent, int slot)
262f1abbce7SDavid van Moolenbroek {
263433d6423SLionel Sambuc 	struct inode *node;
264433d6423SLionel Sambuc 	struct inode_stat stat;
265433d6423SLionel Sambuc 	int i;
266433d6423SLionel Sambuc 
267433d6423SLionel Sambuc 	for (i = 0; pid_files[i].name != NULL; i++) {
268433d6423SLionel Sambuc 		node = get_inode_by_index(parent, i);
269433d6423SLionel Sambuc 		if (node != NULL)
270433d6423SLionel Sambuc 			continue;
271433d6423SLionel Sambuc 
272433d6423SLionel Sambuc 		make_stat(&stat, slot, i);
273433d6423SLionel Sambuc 
274433d6423SLionel Sambuc 		node = add_inode(parent, pid_files[i].name, i, &stat,
275433d6423SLionel Sambuc 		    (index_t)0, (cbdata_t)0);
276433d6423SLionel Sambuc 
277433d6423SLionel Sambuc 		if (node == NULL)
278433d6423SLionel Sambuc 			out_of_inodes();
279433d6423SLionel Sambuc 	}
280433d6423SLionel Sambuc }
281433d6423SLionel Sambuc 
282f1abbce7SDavid van Moolenbroek /*
283f1abbce7SDavid van Moolenbroek  * Construct one requested file entry, or all file entries, in a PID directory.
284433d6423SLionel Sambuc  */
285f1abbce7SDavid van Moolenbroek static void
construct_pid_entries(struct inode * parent,char * name)286f1abbce7SDavid van Moolenbroek construct_pid_entries(struct inode * parent, char * name)
287f1abbce7SDavid van Moolenbroek {
288433d6423SLionel Sambuc 	int slot;
289433d6423SLionel Sambuc 
290433d6423SLionel Sambuc 	slot = get_inode_index(parent);
291433d6423SLionel Sambuc 	assert(slot >= 0 && slot < NR_TASKS + NR_PROCS);
292433d6423SLionel Sambuc 
293433d6423SLionel Sambuc 	/* If this process is already gone, delete the directory now. */
294*305e366fSDavid van Moolenbroek 	if (pid_from_slot(slot) == 0) {
295433d6423SLionel Sambuc 		delete_inode(parent);
296433d6423SLionel Sambuc 
297433d6423SLionel Sambuc 		return;
298433d6423SLionel Sambuc 	}
299433d6423SLionel Sambuc 
300f1abbce7SDavid van Moolenbroek 	/*
301f1abbce7SDavid van Moolenbroek 	 * If a specific file name is being looked up, see if we have to add
302433d6423SLionel Sambuc 	 * an inode for that file.  If the directory contents are being
303433d6423SLionel Sambuc 	 * retrieved, add all files that have not yet been added.
304433d6423SLionel Sambuc 	 */
305433d6423SLionel Sambuc 	if (name != NULL)
306433d6423SLionel Sambuc 		make_one_pid_entry(parent, name, slot);
307433d6423SLionel Sambuc 	else
308433d6423SLionel Sambuc 		make_all_pid_entries(parent, slot);
309433d6423SLionel Sambuc }
310433d6423SLionel Sambuc 
311f1abbce7SDavid van Moolenbroek /*
312f1abbce7SDavid van Moolenbroek  * Data is requested from one of the files in a PID directory. Call the
313433d6423SLionel Sambuc  * function that is responsible for generating the data for that file.
314433d6423SLionel Sambuc  */
315f1abbce7SDavid van Moolenbroek static void
pid_read(struct inode * node)316f1abbce7SDavid van Moolenbroek pid_read(struct inode * node)
317f1abbce7SDavid van Moolenbroek {
318433d6423SLionel Sambuc 	struct inode *parent;
319433d6423SLionel Sambuc 	int slot, index;
320433d6423SLionel Sambuc 
321f1abbce7SDavid van Moolenbroek 	/*
322f1abbce7SDavid van Moolenbroek 	 * Get the slot number of the process.  Note that this currently will
323433d6423SLionel Sambuc 	 * not work for files not in the top-level pid subdirectory.
324433d6423SLionel Sambuc 	 */
325433d6423SLionel Sambuc 	parent = get_parent_inode(node);
326433d6423SLionel Sambuc 
327433d6423SLionel Sambuc 	slot = get_inode_index(parent);
328433d6423SLionel Sambuc 
329433d6423SLionel Sambuc 	/* Get this file's index number. */
330433d6423SLionel Sambuc 	index = get_inode_index(node);
331433d6423SLionel Sambuc 
332433d6423SLionel Sambuc 	/* Call the handler procedure for the file. */
333433d6423SLionel Sambuc 	((void (*)(int))pid_files[index].data)(slot);
334433d6423SLionel Sambuc }
335433d6423SLionel Sambuc 
336f1abbce7SDavid van Moolenbroek /*
337f1abbce7SDavid van Moolenbroek  * The contents of a symbolic link in a PID directory are requested.  This
338f1abbce7SDavid van Moolenbroek  * function is a placeholder for future use.
339433d6423SLionel Sambuc  */
340f1abbce7SDavid van Moolenbroek static int
pid_link(struct inode * __unused node,char * ptr,int max)341f1abbce7SDavid van Moolenbroek pid_link(struct inode * __unused node, char * ptr, int max)
342f1abbce7SDavid van Moolenbroek {
343433d6423SLionel Sambuc 
344433d6423SLionel Sambuc 	/* Nothing yet. */
345433d6423SLionel Sambuc 	strlcpy(ptr, "", max);
346433d6423SLionel Sambuc 
347433d6423SLionel Sambuc 	return OK;
348433d6423SLionel Sambuc }
349433d6423SLionel Sambuc 
350f1abbce7SDavid van Moolenbroek /*
351f1abbce7SDavid van Moolenbroek  * Path name resolution hook, for a specific parent and name pair.  If needed,
352f1abbce7SDavid van Moolenbroek  * update our own view of the system first; after that, determine whether we
353f1abbce7SDavid van Moolenbroek  * need to (re)generate certain files.
354433d6423SLionel Sambuc  */
355f1abbce7SDavid van Moolenbroek int
lookup_hook(struct inode * parent,char * name,cbdata_t __unused cbdata)356f1abbce7SDavid van Moolenbroek lookup_hook(struct inode * parent, char * name, cbdata_t __unused cbdata)
357f1abbce7SDavid van Moolenbroek {
358433d6423SLionel Sambuc 	static clock_t last_update = 0;
359433d6423SLionel Sambuc 	clock_t now;
360433d6423SLionel Sambuc 
361f1abbce7SDavid van Moolenbroek 	/*
362f1abbce7SDavid van Moolenbroek 	 * Update lazily for lookups, as this gets too expensive otherwise.
363433d6423SLionel Sambuc 	 * Alternative: pull in only PM's table?
364433d6423SLionel Sambuc 	 */
365d91f738bSDavid van Moolenbroek 	now = getticks();
366433d6423SLionel Sambuc 
367433d6423SLionel Sambuc 	if (last_update != now) {
368*305e366fSDavid van Moolenbroek 		update_list();
369433d6423SLionel Sambuc 
370433d6423SLionel Sambuc 		last_update = now;
371433d6423SLionel Sambuc 	}
372433d6423SLionel Sambuc 
373f1abbce7SDavid van Moolenbroek 	/*
374f1abbce7SDavid van Moolenbroek 	 * If the parent is the root directory, we must now reconstruct all
375433d6423SLionel Sambuc 	 * entries, because some of them might have been garbage collected.
376433d6423SLionel Sambuc 	 * We must update the entire tree at once; if we update individual
377433d6423SLionel Sambuc 	 * entries, we risk name collisions.
378f1abbce7SDavid van Moolenbroek 	 *
379f1abbce7SDavid van Moolenbroek 	 * If the parent is a process directory, we may need to (re)construct
380433d6423SLionel Sambuc 	 * the entry being looked up.
381433d6423SLionel Sambuc 	 */
382f1abbce7SDavid van Moolenbroek 	if (parent == get_root_inode())
383f1abbce7SDavid van Moolenbroek 		construct_pid_dirs();
384f1abbce7SDavid van Moolenbroek 	else if (dir_is_pid(parent))
385f1abbce7SDavid van Moolenbroek 		/*
386f1abbce7SDavid van Moolenbroek 		 * We might now have deleted our current containing directory;
387433d6423SLionel Sambuc 		 * construct_pid_entries() will take care of this case.
388433d6423SLionel Sambuc 		 */
389433d6423SLionel Sambuc 		construct_pid_entries(parent, name);
39031b6611aSDavid van Moolenbroek 	else
39131b6611aSDavid van Moolenbroek 		/* TODO: skip updating the main tables in this case. */
39231b6611aSDavid van Moolenbroek 		service_lookup(parent, now);
393433d6423SLionel Sambuc 
394433d6423SLionel Sambuc 	return OK;
395433d6423SLionel Sambuc }
396433d6423SLionel Sambuc 
397f1abbce7SDavid van Moolenbroek /*
398f1abbce7SDavid van Moolenbroek  * Directory entry retrieval hook, for potentially all files in a directory.
399f1abbce7SDavid van Moolenbroek  * Make sure that all files that are supposed to be returned, are actually part
400f1abbce7SDavid van Moolenbroek  * of the virtual tree.
401433d6423SLionel Sambuc  */
402f1abbce7SDavid van Moolenbroek int
getdents_hook(struct inode * node,cbdata_t __unused cbdata)403f1abbce7SDavid van Moolenbroek getdents_hook(struct inode * node, cbdata_t __unused cbdata)
404f1abbce7SDavid van Moolenbroek {
405433d6423SLionel Sambuc 
406433d6423SLionel Sambuc 	if (node == get_root_inode()) {
407*305e366fSDavid van Moolenbroek 		update_list();
408433d6423SLionel Sambuc 
409433d6423SLionel Sambuc 		construct_pid_dirs();
410f1abbce7SDavid van Moolenbroek 	} else if (dir_is_pid(node))
411433d6423SLionel Sambuc 		construct_pid_entries(node, NULL /*name*/);
41231b6611aSDavid van Moolenbroek 	else
41331b6611aSDavid van Moolenbroek 		service_getdents(node);
414433d6423SLionel Sambuc 
415433d6423SLionel Sambuc 	return OK;
416433d6423SLionel Sambuc }
417433d6423SLionel Sambuc 
418f1abbce7SDavid van Moolenbroek /*
419f1abbce7SDavid van Moolenbroek  * Regular file read hook.  Call the appropriate callback function to generate
420f1abbce7SDavid van Moolenbroek  * and return the data.
421f1abbce7SDavid van Moolenbroek  */
422f1abbce7SDavid van Moolenbroek ssize_t
read_hook(struct inode * node,char * ptr,size_t len,off_t off,cbdata_t cbdata)423f1abbce7SDavid van Moolenbroek read_hook(struct inode * node, char * ptr, size_t len, off_t off,
4245eefd0feSDavid van Moolenbroek 	cbdata_t cbdata)
425433d6423SLionel Sambuc {
42631b6611aSDavid van Moolenbroek 	struct inode *parent;
427433d6423SLionel Sambuc 
4285eefd0feSDavid van Moolenbroek 	buf_init(ptr, len, off);
429433d6423SLionel Sambuc 
430433d6423SLionel Sambuc 	/* Populate the buffer with the proper content. */
43131b6611aSDavid van Moolenbroek 	if (get_inode_index(node) != NO_INDEX) {
43231b6611aSDavid van Moolenbroek 		parent = get_parent_inode(node);
43331b6611aSDavid van Moolenbroek 
43431b6611aSDavid van Moolenbroek 		/* The PID directories are indexed; service/ is not. */
43531b6611aSDavid van Moolenbroek 		if (get_inode_index(parent) != NO_INDEX)
436433d6423SLionel Sambuc 			pid_read(node);
437f1abbce7SDavid van Moolenbroek 		else
43831b6611aSDavid van Moolenbroek 			service_read(node);
43931b6611aSDavid van Moolenbroek 	} else
440433d6423SLionel Sambuc 		((void (*)(void))cbdata)();
441433d6423SLionel Sambuc 
4425eefd0feSDavid van Moolenbroek 	return buf_result();
443433d6423SLionel Sambuc }
444433d6423SLionel Sambuc 
445f1abbce7SDavid van Moolenbroek /*
446f1abbce7SDavid van Moolenbroek  * Symbolic link resolution hook.  Not used yet.
447433d6423SLionel Sambuc  */
448f1abbce7SDavid van Moolenbroek int
rdlink_hook(struct inode * node,char * ptr,size_t max,cbdata_t __unused cbdata)449f1abbce7SDavid van Moolenbroek rdlink_hook(struct inode * node, char * ptr, size_t max,
450f1abbce7SDavid van Moolenbroek 	cbdata_t __unused cbdata)
451f1abbce7SDavid van Moolenbroek {
452433d6423SLionel Sambuc 	struct inode *parent;
453433d6423SLionel Sambuc 
454433d6423SLionel Sambuc 	/* Get the parent inode. */
455433d6423SLionel Sambuc 	parent = get_parent_inode(node);
456433d6423SLionel Sambuc 
457f1abbce7SDavid van Moolenbroek 	/* If the parent inode is a pid directory, call the pid handler. */
458433d6423SLionel Sambuc 	if (parent != NULL && dir_is_pid(parent))
459433d6423SLionel Sambuc 		pid_link(node, ptr, max);
460433d6423SLionel Sambuc 
461433d6423SLionel Sambuc 	return OK;
462433d6423SLionel Sambuc }
463