xref: /minix/minix/lib/libpuffs/open.c (revision 0a6a1f1d)
1 /* Created (MFS based):
2  *   June 2011 (Evgeniy Ivanov)
3  */
4 
5 #include "fs.h"
6 
7 /*===========================================================================*
8  *				fs_create				     *
9  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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