nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vfs.c
Go to the documentation of this file.
1 #include <slibc.h>
2 #include <sys/types.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6 #include <stddef.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <assert.h>
10 
11 #include <object.h>
12 #include <list.h>
13 #include <vfs.h>
14 #include <vfs0.h>
15 
16 #include <debug.h>
17 
18 static struct sinfo s_sinfo;
19 static struct ninfo s_root;
20 
21 int vfs_init(void)
22 {
24  s_root.type = NINFO_TYPE_FOLDER;
25 
32  s_root.head_sibling = 0;
33  s_root.si = &s_sinfo;
34  s_root.id = 0;
35  s_root.size = 0;
36  s_root.refcnt = 0;
37  s_root.deleted = 0;
38  s_root.priv = NULL;
39 
40  s_root.nops.open = NULL;
41  s_root.nops.close = NULL;
42  s_root.nops.read = NULL;
43  s_root.nops.write = NULL;
44  s_root.nops.lseek = NULL;
45  s_root.nops.ioctl = NULL;
46 
47  INIT_LIST_HEAD(&s_root.sibling);
48  INIT_LIST_HEAD(&s_root.child);
49  INIT_LIST_HEAD(&s_root.sinfo);
50 
51  INIT_LIST_HEAD(&s_sinfo.head);
52  s_sinfo.get_ninfo = NULL;
53  s_sinfo.fill_ninfo = NULL;
54  s_sinfo.del_ninfo = NULL;
55  s_sinfo.refresh_children = NULL;
56  s_sinfo.refcnt = 0;
57  s_sinfo.priv = NULL;
58 
59  return 0;
60 }
61 
62 int vfs_attach_storage(struct ninfo *node, struct sinfo *sb)
63 {
64  list_add_tail(&sb->head, &node->sinfo);
65  return 0;
66 }
67 
69 {
70  return 0;
71 }
72 
73 static inline void vfs_free_ninfo(struct ninfo *node)
74 {
75  struct sinfo *si;
76 
77  if (node == &s_root) {
78  return;
79  }
80 
81  si = node->si;
82 
83  if (si && si->del_ninfo) {
84  si->del_ninfo(si, node);
85  }
86 
87  list_del(&node->child);
88  list_del(&node->sibling);
89  free(node->name);
90  free(node);
91 }
92 
93 int vfs_del_ninfo(struct ninfo *root)
94 {
95  struct list_head *pos;
96  struct list_head *n;
97  struct ninfo *tmp;
98  struct ninfo *node;
99  struct sinfo *sinfo;
100  struct stack {
101  struct list_head head;
102  struct ninfo *node;
103  } *item;
104  LIST_HEAD(stack);
105 
106  if (root == &s_root) {
107  return -EINVAL;
108  }
109 
110  sinfo = root->si;
111 
112  if (sinfo->get_ninfo) {
113  tmp = sinfo->get_ninfo(sinfo, ROOT_NINFO);
114  } else {
115  tmp = NULL;
116  }
117 
119  if (root == tmp) {
120  return -EINVAL;
121  }
122 
123  node = vfs_get_ninfo_child(root);
124  while (node) {
125  tmp = vfs_get_ninfo_child(node);
126  if (tmp) {
127  item = malloc(sizeof(*item));
128  if (!item) {
129  goto nomem;
130  }
131 
132  item->node = node;
133  list_add_tail(&item->head, &stack);
134 
135  node = tmp;
136  continue;
137  }
138 
139  tmp = vfs_get_ninfo_next_sibling(node);
140  if (tmp) {
141  if (node->head_sibling) {
142  struct ninfo *parent;
143  parent = vfs_get_ninfo_parent(node);
144  list_link(&tmp->child, &parent->child);
145  tmp->head_sibling = 1;
146  }
147 
148  vfs_free_ninfo(node);
149  node = tmp;
150  continue;
151  }
152 
153  vfs_free_ninfo(node);
154 
155  node = NULL;
156  while (!node) {
157  if (stack.prev == &stack) {
158  node = NULL;
159  break;
160  }
161 
162  item = list_entry(stack.prev, struct stack, head);
163  list_del(&item->head);
164  node = item->node;
165  free(item);
166 
167  tmp = vfs_get_ninfo_next_sibling(node);
168  vfs_free_ninfo(node);
169  node = tmp;
170  }
171  }
172 
173  vfs_free_ninfo(root);
174  return 0;
175 
176 nomem:
177  list_for_each_safe(pos, n, &stack) {
178  item = list_entry(pos, struct stack, head);
179  list_del(pos);
180  free(item);
181  }
182  return -ENOMEM;
183 }
184 
185 static inline struct ninfo *get_root_if_attached(struct ninfo *node)
186 {
187  struct sinfo *si;
188 
189  si = vfs_get_last_sinfo(node);
190  if (!si || !si->get_ninfo) {
191  return NULL;
192  }
193 
194  node = si->get_ninfo(si, ROOT_NINFO);
195  if (!node) {
196  return NULL;
197  }
198 
199  if (si->refresh_children) {
200  si->refresh_children(si, node);
201  }
202 
203  return node;
204 }
205 
206 struct ninfo *vfs_get_ninfo(struct sinfo *sinfo, struct ninfo *node,
207  const char *path)
208 {
209  const char *p;
210  int idx;
211  struct ninfo *tmp;
212  struct list_head *pos;
213  enum {
214  DOT,
215  DOTDOT,
216  NAME,
217  } state;
218 
219  if (!path) {
220  return NULL;
221  }
222 
223  idx = 0;
224  p = path;
225  state = NAME;
226 
227  if (!node) {
228  if (sinfo && sinfo->get_ninfo) {
229  node = sinfo->get_ninfo(sinfo, ROOT_NINFO);
230  }
231 
232  if (!node) {
233  node = &s_root;
234  }
235  }
236 
237  do {
238  switch (p[idx]) {
239  case '\0':
240  case '/':
241  if (state == DOT) {
242  break;
243  }
244 
245  if (state == DOTDOT) {
246  tmp = vfs_get_ninfo_parent(node);
247  if (tmp) {
248  node = tmp;
249  }
250  break;
251  }
252 
253  if (!idx) {
254  struct ninfo *root;
255 
256  /* Skip empty */
257  idx--;
258  p++;
259 
260  if (*p == '/') {
261  break;
262  }
263 
264  root = get_root_if_attached(node);
265  if (root) {
266  node = root;
267  }
268 
269  /* Ignore last '/' and '///...' */
270  if (*p == '\0') {
271  return node;
272  }
273 
274  /* Get the children of current node */
275  node = vfs_get_ninfo_child(node);
276  break;
277  }
278 
279 
280  /* Check the siblings */
281  tmp = NULL;
282  list_for_each(pos, &node->sibling) {
283  tmp = list_entry(pos, struct ninfo, sibling);
284  if (!strncmp(tmp->name, p, idx)) {
285  if (!tmp->name[idx]) {
286  break;
287  }
288  }
289 
290  tmp = NULL;
291  }
292 
293  if (!tmp && !strncmp(node->name, p, idx)) {
294  /* Check the current node first */
295  if (!node->name[idx]) {
296  tmp = node;
297  }
298  }
299 
300  if (!p[idx]) {
301  return tmp;
302  }
303 
304  p += (idx + 1); /* +1 = counting '/' */
305  idx = -1; /* It will be increased to ZERO */
306 
307  node = vfs_get_ninfo_child(tmp);
308  break;
309 
310  case '.':
311  if (!idx) {
312  state = DOT;
313  break;
314  }
315 
316  if (state == DOT) {
317  state = DOTDOT;
318  break;
319  }
320  default:
321  state = NAME;
322  break;
323  }
324 
325  idx++;
326  } while (node);
327 
328  /* Get the root node of the attached storage on this node */
329  if (node) {
330  tmp = get_root_if_attached(node);
331  if (tmp) {
332  node = tmp;
333  }
334  }
335 
336  return node;
337 }
338 
339 struct ninfo *vfs_new_ninfo(struct sinfo *sinfo, struct ninfo *parent,
340  const char *name, void *info)
341 {
342  struct ninfo *ninfo;
343  char *dup_name;
344 
345  if (!name) {
346  return NULL;
347  }
348 
349  if (parent) {
350  if (parent->type != NINFO_TYPE_FOLDER) {
351  return NULL;
352  }
353 
354  if (!sinfo) {
355  sinfo = parent->si;
356  }
357  }
358 
359  if (!sinfo) {
360  return NULL;
361  }
362 
363  dup_name = NULL;
364  if (name) {
365  dup_name = strdup(name);
366  if (!dup_name) {
367  return NULL;
368  }
369  }
370 
371  ninfo = malloc(sizeof(*ninfo));
372  if (!ninfo) {
373  free(dup_name);
374  return NULL;
375  }
376 
377  ninfo->name = dup_name;
378  ninfo->si = sinfo;
379  ninfo->refcnt = 0;
380  ninfo->deleted = 0;
381  ninfo->priv = NULL;
382  ninfo->head_sibling = 0;
383  INIT_LIST_HEAD(&ninfo->sibling);
384  INIT_LIST_HEAD(&ninfo->child);
385  INIT_LIST_HEAD(&ninfo->sinfo);
386 
387  if (sinfo->fill_ninfo && sinfo->fill_ninfo(sinfo, parent, ninfo, info) < 0) {
388  free(dup_name);
389  free(ninfo);
390  return NULL;
391  }
392 
393  if (parent) {
394  struct ninfo *child;
395 
396  child = vfs_get_ninfo_child(parent);
397  if (!child) {
398  ninfo->head_sibling = 1;
399  list_add(&ninfo->child, &parent->child);
400  } else {
401  list_add_tail(&ninfo->sibling, &child->sibling);
402  }
403  }
404 
405  return ninfo;
406 }
407 
408 struct ninfo *vfs_get_ninfo_child(struct ninfo *node)
409 {
410  struct sinfo *si;
411  struct ninfo *child;
412  struct ninfo *root;
413 
414  if (!node || node->type != NINFO_TYPE_FOLDER) {
415  return NULL;
416  }
417 
418  root = node;
419 
420  si = node->si;
421  if (si) {
422  if (si->refresh_children) {
423  si->refresh_children(si, node);
424  }
425 
426  if (si->get_ninfo) {
427  root = si->get_ninfo(si, ROOT_NINFO);
428  }
429  }
430 
431  child = list_entry(node->child.next, struct ninfo, child);
432  if (child == root || child == node || !child->head_sibling) {
433  return NULL;
434  }
435 
436  return child;
437 }
438 
439 struct ninfo *vfs_get_ninfo_parent(struct ninfo *node)
440 {
441  struct sinfo *si;
442  struct ninfo *parent;
443 
444  si = node->si;
445  if (si && si->get_ninfo) {
446  if (si->get_ninfo(si, ROOT_NINFO) == node) {
447  return NULL;
448  }
449  }
450 
451  parent = list_entry(node->child.prev, struct ninfo, child);
452  if (parent == node) {
453  return NULL;
454  }
455 
456  return parent;
457 }
458 
460 {
461  struct ninfo *next;
462 
463  next = list_entry(node->sibling.next, struct ninfo, sibling);
464  if (next == node || next->head_sibling) {
465  return NULL;
466  }
467 
468  return next;
469 }
470 
472 {
473  struct ninfo *prev;
474 
475  if (node->head_sibling) {
476  return NULL;
477  }
478 
479  prev = list_entry(node->sibling.prev, struct ninfo, sibling);
480  if (prev == node) {
481  return NULL;
482  }
483 
484  return prev;
485 }
486 
487 struct sinfo *vfs_get_last_sinfo(struct ninfo *node)
488 {
489  if (node->type != NINFO_TYPE_FOLDER) {
490  return NULL;
491  }
492 
493  if (node->sinfo.prev == &node->sinfo) {
494  return NULL;
495  }
496 
497  return list_entry(node->sinfo.prev, struct sinfo, head);
498 }
499 
500 struct ninfo *vfs_new_dev_ninfo(struct sinfo *sinfo, struct ninfo *parent,
501  const char *name, dev_t device, struct ninfo_ops *nops)
502 {
503  struct ninfo *ninfo;
504  struct ninfo_dev *priv;
505  char *dup_name;
506 
507  if (!name) {
508  return NULL;
509  }
510 
511  if (parent) {
512  if (parent->type != NINFO_TYPE_FOLDER) {
513  return NULL;
514  }
515 
516  if (!sinfo) {
517  sinfo = parent->si;
518  }
519  }
520 
521  if (!sinfo) {
522  return NULL;
523  }
524 
525  dup_name = NULL;
526  if (name) {
527  dup_name = strdup(name);
528  if (!dup_name) {
529  return NULL;
530  }
531  }
532 
533  ninfo = malloc(sizeof(*ninfo));
534  if (!ninfo) {
535  free(dup_name);
536  return NULL;
537  }
538 
539  priv = malloc(sizeof(*priv));
540  if (!priv) {
541  free(dup_name);
542  free(ninfo);
543  return NULL;
544  }
545 
546  priv->device = device;
547 
548  ninfo->name = dup_name;
549  ninfo->si = sinfo;
550  ninfo->refcnt = 0;
551  ninfo->deleted = 0;
552  ninfo->priv = priv;
553  ninfo->head_sibling = 0;
554  ninfo->type = NINFO_TYPE_DEVICE;
555  ninfo->nops = *nops;
556  INIT_LIST_HEAD(&ninfo->sibling);
557  INIT_LIST_HEAD(&ninfo->child);
558  INIT_LIST_HEAD(&ninfo->sinfo);
559 
560  if (parent) {
561  struct ninfo *child;
562 
563  child = vfs_get_ninfo_child(parent);
564  if (!child) {
565  ninfo->head_sibling = 1;
566  list_add(&ninfo->child, &parent->child);
567  } else {
568  list_add_tail(&ninfo->sibling, &child->sibling);
569  }
570  }
571 
572  return ninfo;
573 }
574 
575 /* End of a file */