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