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