rev |
line source |
nuclear@0
|
1 #include <string.h>
|
nuclear@0
|
2 #include <pthread.h>
|
nuclear@0
|
3 #include <alloca.h>
|
nuclear@0
|
4 #include "pvfs.h"
|
nuclear@0
|
5 #include "vnode.h"
|
nuclear@0
|
6
|
nuclear@0
|
7 static void add_child(struct vnode *parent, struct vnode *child);
|
nuclear@0
|
8 static struct vnode *find_child(struct vnode *node, const char *name);
|
nuclear@0
|
9
|
nuclear@0
|
10 static struct vnode *root;
|
nuclear@0
|
11 static struct vnode *cwd;
|
nuclear@0
|
12
|
nuclear@0
|
13 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
nuclear@0
|
14
|
nuclear@0
|
15
|
nuclear@0
|
16 struct vnode *vnode_create(const char *name)
|
nuclear@0
|
17 {
|
nuclear@0
|
18 struct vnode *n;
|
nuclear@0
|
19
|
nuclear@0
|
20 if(!(n = calloc(1, sizeof *n)) || !(n->name = strdup(name))) {
|
nuclear@0
|
21 pvfs_errno = ENOMEM;
|
nuclear@0
|
22 return 0;
|
nuclear@0
|
23 }
|
nuclear@0
|
24 return n;
|
nuclear@0
|
25 }
|
nuclear@0
|
26
|
nuclear@0
|
27 struct vnode *vnode_create_file(const char *name, PVFS_FILE *fp)
|
nuclear@0
|
28 {
|
nuclear@0
|
29 struct vnode *n;
|
nuclear@0
|
30
|
nuclear@0
|
31 if(!(n = vnode_create(name))) {
|
nuclear@0
|
32 return 0;
|
nuclear@0
|
33 }
|
nuclear@0
|
34 n->type = VNODE_FILE;
|
nuclear@0
|
35 n->obj = fp;
|
nuclear@0
|
36 return n;
|
nuclear@0
|
37 }
|
nuclear@0
|
38
|
nuclear@0
|
39 struct vnode *vnode_create_dir(const char *name, PVFS_DIR *dir)
|
nuclear@0
|
40 {
|
nuclear@0
|
41 struct vnode *n;
|
nuclear@0
|
42
|
nuclear@0
|
43 if(!(n = vnode_create(name))) {
|
nuclear@0
|
44 return 0;
|
nuclear@0
|
45 }
|
nuclear@0
|
46 n->type = VNODE_DIR;
|
nuclear@0
|
47 n->obj = dir;
|
nuclear@0
|
48 return n;
|
nuclear@0
|
49 }
|
nuclear@0
|
50
|
nuclear@0
|
51 void vnode_free(struct vnode *n)
|
nuclear@0
|
52 {
|
nuclear@0
|
53 free(n->name);
|
nuclear@0
|
54 free(n);
|
nuclear@0
|
55 }
|
nuclear@0
|
56
|
nuclear@0
|
57 static void destroy_tree_rec(struct vnode *tree)
|
nuclear@0
|
58 {
|
nuclear@0
|
59 struct vnode *c = tree->childlist;
|
nuclear@0
|
60 while(c) {
|
nuclear@0
|
61 struct vnode *tmp = c;
|
nuclear@0
|
62 c = c->next;
|
nuclear@0
|
63 vnode_destroy_tree(tmp);
|
nuclear@0
|
64 }
|
nuclear@0
|
65 vnode_free(tree);
|
nuclear@0
|
66 }
|
nuclear@0
|
67
|
nuclear@0
|
68 void vnode_destroy_tree(struct vnode *tree)
|
nuclear@0
|
69 {
|
nuclear@0
|
70 pthread_mutex_lock(&mutex);
|
nuclear@0
|
71 destroy_tree_rec(tree);
|
nuclear@0
|
72 pthread_mutex_unlock(&mutex);
|
nuclear@0
|
73 }
|
nuclear@0
|
74
|
nuclear@0
|
75 struct vnode *vnode_lookup(const char *const_path)
|
nuclear@0
|
76 {
|
nuclear@0
|
77 struct vnode *node, *res = 0;
|
nuclear@0
|
78 char *path;
|
nuclear@0
|
79
|
nuclear@0
|
80 path = alloca(strlen(const_path) + 1);
|
nuclear@0
|
81 strcpy(path, const_path);
|
nuclear@0
|
82
|
nuclear@0
|
83 pthread_mutex_lock(&mutex);
|
nuclear@0
|
84
|
nuclear@0
|
85 if(path[0] == '/') {
|
nuclear@0
|
86 node = root;
|
nuclear@0
|
87 path++;
|
nuclear@0
|
88 } else {
|
nuclear@0
|
89 node = cwd;
|
nuclear@0
|
90 }
|
nuclear@0
|
91
|
nuclear@0
|
92 while(path && *path) {
|
nuclear@0
|
93 char *slash = strchr(path + 1, '/');
|
nuclear@0
|
94 if(slash) {
|
nuclear@0
|
95 *slash = 0;
|
nuclear@0
|
96 }
|
nuclear@0
|
97
|
nuclear@0
|
98 if(!(node = find_child(node, path))) {
|
nuclear@0
|
99 pvfs_errno = ENOENT;
|
nuclear@0
|
100 goto done;
|
nuclear@0
|
101 }
|
nuclear@0
|
102 path = slash ? slash + 1 : 0;
|
nuclear@0
|
103 }
|
nuclear@0
|
104 res = node;
|
nuclear@0
|
105
|
nuclear@0
|
106 done:
|
nuclear@0
|
107 pthread_mutex_unlock(&mutex);
|
nuclear@0
|
108 return res;
|
nuclear@0
|
109 }
|
nuclear@0
|
110
|
nuclear@0
|
111 int vnode_chdir(const char *name)
|
nuclear@0
|
112 {
|
nuclear@0
|
113 struct vnode *node = vnode_lookup(name);
|
nuclear@0
|
114 if(node) {
|
nuclear@0
|
115 /* XXX race condition with delete tree, shouldn't really happen... */
|
nuclear@0
|
116 pthread_mutex_lock(&mutex);
|
nuclear@0
|
117 cwd = node;
|
nuclear@0
|
118 pthread_mutex_unlock(&mutex);
|
nuclear@0
|
119 return 0;
|
nuclear@0
|
120 }
|
nuclear@0
|
121 return -1;
|
nuclear@0
|
122 }
|
nuclear@0
|
123
|
nuclear@0
|
124 int vnode_mkdir(struct vnode *parent, const char *name)
|
nuclear@0
|
125 {
|
nuclear@0
|
126 struct vnode *n;
|
nuclear@0
|
127
|
nuclear@0
|
128 if(!parent) {
|
nuclear@0
|
129 if(root || strcmp(name, "/") != 0) {
|
nuclear@0
|
130 pvfs_errno = EEXIST;
|
nuclear@0
|
131 return -1;
|
nuclear@0
|
132 }
|
nuclear@0
|
133 }
|
nuclear@0
|
134
|
nuclear@0
|
135 if(!(n = vnode_create_dir(name, 0))) {
|
nuclear@0
|
136 return -1;
|
nuclear@0
|
137 }
|
nuclear@0
|
138 add_child(parent, n);
|
nuclear@0
|
139 return 0;
|
nuclear@0
|
140 }
|
nuclear@0
|
141
|
nuclear@0
|
142 static void add_child(struct vnode *parent, struct vnode *child)
|
nuclear@0
|
143 {
|
nuclear@0
|
144 pthread_mutex_lock(&mutex);
|
nuclear@0
|
145
|
nuclear@0
|
146 child->parent = parent;
|
nuclear@0
|
147 child->next = parent->childlist;
|
nuclear@0
|
148 parent->childlist = child;
|
nuclear@0
|
149
|
nuclear@0
|
150 pthread_mutex_unlock(&mutex);
|
nuclear@0
|
151 }
|
nuclear@0
|
152
|
nuclear@0
|
153 static struct vnode *find_child(struct vnode *node, const char *name)
|
nuclear@0
|
154 {
|
nuclear@0
|
155 struct vnode *c = node->childlist;
|
nuclear@0
|
156 while(c) {
|
nuclear@0
|
157 if(strcmp(c->name, name) == 0) {
|
nuclear@0
|
158 return c;
|
nuclear@0
|
159 }
|
nuclear@0
|
160 c = c->next;
|
nuclear@0
|
161 }
|
nuclear@0
|
162 return 0;
|
nuclear@0
|
163 }
|