1 /* Created (MFS based):
2 * June 2011 (Evgeniy Ivanov)
3 */
4
5 #include "fs.h"
6
7 /*===========================================================================*
8 * fs_create *
9 *===========================================================================*/
fs_create(ino_t dir_nr,char * name,mode_t mode,uid_t uid,gid_t gid,struct fsdriver_node * node)10 int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
11 struct fsdriver_node *node)
12 {
13 int r;
14 struct puffs_node *pn_dir;
15 struct puffs_node *pn;
16 struct puffs_newinfo pni;
17 struct puffs_kcn pkcnp;
18 PUFFS_MAKECRED(pcr, &global_kcred);
19 struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
20 struct vattr va;
21 struct timespec cur_time;
22
23 if (global_pu->pu_ops.puffs_node_create == NULL) {
24 lpuffs_debug("No puffs_node_create");
25 return(ENFILE);
26 }
27
28 /* Copy the last component (i.e., file name) */
29 pcn.pcn_namelen = strlen(name);
30 assert(pcn.pcn_namelen <= NAME_MAX);
31 strcpy(pcn.pcn_name, name);
32
33 /* Get last directory pnode (i.e., directory that will hold the new pnode) */
34 if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL)
35 return(ENOENT);
36
37 memset(&pni, 0, sizeof(pni));
38 pni.pni_cookie = (void** )&pn;
39
40 (void)clock_time(&cur_time);
41
42 memset(&va, 0, sizeof(va));
43 va.va_type = VREG;
44 va.va_mode = mode;
45 va.va_uid = uid;
46 va.va_gid = gid;
47 va.va_atime = va.va_mtime = va.va_ctime = cur_time;
48
49 if (buildpath) {
50 r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
51 if (r) {
52 lpuffs_debug("pathbuild error\n");
53 return(ENOENT);
54 }
55 }
56
57 r = global_pu->pu_ops.puffs_node_create(global_pu, pn_dir, &pni, &pcn, &va);
58 if (buildpath) {
59 if (r) {
60 global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
61 } else {
62 struct puffs_node *_pn;
63
64 _pn = PU_CMAP(global_pu, pn);
65 _pn->pn_po = pcn.pcn_po_full;
66 }
67 }
68
69 if (r != OK) {
70 if (r > 0) r = -r;
71 return(r);
72 }
73
74 /* Open pnode */
75 pn->pn_count++;
76
77 update_timens(pn_dir, MTIME | CTIME, &cur_time);
78
79 /* Reply message */
80 node->fn_ino_nr = pn->pn_va.va_fileid;
81 node->fn_mode = pn->pn_va.va_mode;
82 node->fn_size = pn->pn_va.va_size;
83 node->fn_uid = pn->pn_va.va_uid;
84 node->fn_gid = pn->pn_va.va_gid;
85 node->fn_dev = NO_DEV;
86
87 return(OK);
88 }
89
90
91 /*===========================================================================*
92 * fs_mknod *
93 *===========================================================================*/
fs_mknod(ino_t dir_nr,char * name,mode_t mode,uid_t uid,gid_t gid,dev_t dev)94 int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
95 dev_t dev)
96 {
97 int r;
98 struct puffs_node *pn_dir;
99 struct puffs_node *pn;
100 struct puffs_newinfo pni;
101 struct puffs_kcn pkcnp;
102 PUFFS_MAKECRED(pcr, &global_kcred);
103 struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
104 struct vattr va;
105 struct timespec cur_time;
106
107 if (global_pu->pu_ops.puffs_node_mknod == NULL) {
108 lpuffs_debug("No puffs_node_mknod");
109 return(ENFILE);
110 }
111
112 /* Copy the last component */
113 pcn.pcn_namelen = strlen(name);
114 assert(pcn.pcn_namelen <= NAME_MAX);
115 strcpy(pcn.pcn_name, name);
116
117 /* Get last directory pnode */
118 if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL)
119 return(ENOENT);
120
121 memset(&pni, 0, sizeof(pni));
122 pni.pni_cookie = (void** )&pn;
123
124 (void)clock_time(&cur_time);
125
126 memset(&va, 0, sizeof(va));
127 va.va_type = VDIR;
128 va.va_mode = mode;
129 va.va_uid = uid;
130 va.va_gid = gid;
131 va.va_rdev = dev;
132 va.va_atime = va.va_mtime = va.va_ctime = cur_time;
133
134 if (buildpath) {
135 if (puffs_path_pcnbuild(global_pu, &pcn, pn_dir) != 0) {
136 lpuffs_debug("pathbuild error\n");
137 return(ENOENT);
138 }
139 }
140
141 r = global_pu->pu_ops.puffs_node_mknod(global_pu, pn_dir, &pni, &pcn, &va);
142 if (buildpath) {
143 if (r) {
144 global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
145 } else {
146 struct puffs_node *_pn;
147
148 _pn = PU_CMAP(global_pu, pn);
149 _pn->pn_po = pcn.pcn_po_full;
150 }
151 }
152
153 if (r != OK) {
154 if (r > 0) r = -r;
155 return(r);
156 }
157
158 update_timens(pn_dir, MTIME | CTIME, &cur_time);
159
160 return(OK);
161 }
162
163
164 /*===========================================================================*
165 * fs_mkdir *
166 *===========================================================================*/
fs_mkdir(ino_t dir_nr,char * name,mode_t mode,uid_t uid,gid_t gid)167 int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid)
168 {
169 int r;
170 struct puffs_node *pn_dir;
171 struct puffs_node *pn;
172 struct puffs_newinfo pni;
173 struct puffs_kcn pkcnp;
174 PUFFS_MAKECRED(pcr, &global_kcred);
175 struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
176 struct vattr va;
177 struct timespec cur_time;
178
179 if (global_pu->pu_ops.puffs_node_mkdir == NULL) {
180 lpuffs_debug("No puffs_node_mkdir");
181 return(ENFILE);
182 }
183
184 /* Copy the last component */
185 pcn.pcn_namelen = strlen(name);
186 assert(pcn.pcn_namelen <= NAME_MAX);
187 strcpy(pcn.pcn_name, name);
188
189 /* Get last directory pnode */
190 if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL)
191 return(ENOENT);
192
193 (void)clock_time(&cur_time);
194
195 memset(&pni, 0, sizeof(pni));
196 pni.pni_cookie = (void** )&pn;
197
198 memset(&va, 0, sizeof(va));
199 va.va_type = VDIR;
200 va.va_mode = mode;
201 va.va_uid = uid;
202 va.va_gid = gid;
203 va.va_atime = va.va_mtime = va.va_ctime = cur_time;
204
205 if (buildpath) {
206 r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
207 if (r) {
208 lpuffs_debug("pathbuild error\n");
209 return(ENOENT);
210 }
211 }
212
213 r = global_pu->pu_ops.puffs_node_mkdir(global_pu, pn_dir, &pni, &pcn, &va);
214 if (buildpath) {
215 if (r) {
216 global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
217 } else {
218 struct puffs_node *_pn;
219
220 _pn = PU_CMAP(global_pu, pn);
221 _pn->pn_po = pcn.pcn_po_full;
222 }
223 }
224
225 if (r != OK) {
226 if (r > 0) r = -r;
227 return(r);
228 }
229
230 update_timens(pn_dir, MTIME | CTIME, &cur_time);
231
232 return(OK);
233 }
234
235
236 /*===========================================================================*
237 * fs_slink *
238 *===========================================================================*/
fs_slink(ino_t dir_nr,char * name,uid_t uid,gid_t gid,struct fsdriver_data * data,size_t bytes)239 int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid,
240 struct fsdriver_data *data, size_t bytes)
241 {
242 int r;
243 struct pnode *pn; /* pnode containing symbolic link */
244 struct pnode *pn_dir; /* directory containing link */
245 char target[PATH_MAX + 1]; /* target path */
246 struct puffs_newinfo pni;
247 struct puffs_kcn pkcnp;
248 PUFFS_MAKECRED(pcr, &global_kcred);
249 struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
250 struct vattr va;
251 struct timespec cur_time;
252
253 /* Copy the link name's last component */
254 pcn.pcn_namelen = strlen(name);
255 if (pcn.pcn_namelen > NAME_MAX)
256 return(ENAMETOOLONG);
257 strcpy(pcn.pcn_name, name);
258
259 if (bytes >= PATH_MAX)
260 return(ENAMETOOLONG);
261
262 /* Copy the target path (note that it's not null terminated) */
263 if ((r = fsdriver_copyin(data, 0, target, bytes)) != OK)
264 return r;
265
266 target[bytes] = '\0';
267
268 if (strlen(target) != bytes) {
269 /* This can happen if the user provides a buffer
270 * with a \0 in it. This can cause a lot of trouble
271 * when the symlink is used later. We could just use
272 * the strlen() value, but we want to let the user
273 * know he did something wrong. ENAMETOOLONG doesn't
274 * exactly describe the error, but there is no
275 * ENAMETOOWRONG.
276 */
277 return(ENAMETOOLONG);
278 }
279
280 if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL)
281 return(EINVAL);
282
283 memset(&pni, 0, sizeof(pni));
284 pni.pni_cookie = (void** )&pn;
285
286 (void)clock_time(&cur_time);
287
288 memset(&va, 0, sizeof(va));
289 va.va_type = VLNK;
290 va.va_mode = (I_SYMBOLIC_LINK | RWX_MODES);
291 va.va_uid = uid;
292 va.va_gid = gid;
293 va.va_atime = va.va_mtime = va.va_ctime = cur_time;
294
295 if (buildpath) {
296 r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
297 if (r) {
298 lpuffs_debug("pathbuild error\n");
299 return(ENOENT);
300 }
301 }
302
303 r = global_pu->pu_ops.puffs_node_symlink(global_pu, pn_dir, &pni, &pcn, &va, target);
304 if (buildpath) {
305 if (r) {
306 global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
307 } else {
308 struct puffs_node *_pn;
309
310 _pn = PU_CMAP(global_pu, pn);
311 _pn->pn_po = pcn.pcn_po_full;
312 }
313 }
314
315 if (r > 0) r = -r;
316
317 return(r);
318 }
319