Changeset 2c448fb in mainline for uspace/srv
- Timestamp:
- 2008-02-27T22:49:48Z (17 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7fe1f75
- Parents:
- 56976a17
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/tmpfs/tmpfs_ops.c
r56976a17 r2c448fb 46 46 #include <string.h> 47 47 #include <stdio.h> 48 #include <dirent.h>49 48 #include <assert.h> 50 49 #include <sys/types.h> 51 50 #include <libadt/hash_table.h> 52 51 #include <as.h> 52 #include <libfs.h> 53 53 54 54 #define min(a, b) ((a) < (b) ? (a) : (b)) 55 55 #define max(a, b) ((a) > (b) ? (a) : (b)) 56 56 57 #define PLB_GET_CHAR(i) (tmpfs_reg.plb_ro[(i) % PLB_SIZE])58 59 57 #define DENTRIES_BUCKETS 256 60 58 61 #define TMPFS_GET_INDEX(x) (((tmpfs_dentry_t *)(x))->index) 62 #define TMPFS_GET_LNKCNT(x) 1 59 /* 60 * For now, we don't distinguish between different dev_handles/instances. All 61 * requests resolve to the only instance, rooted in the following variable. 62 */ 63 static tmpfs_dentry_t *root; 64 65 /* 66 * Implementation of the libfs interface. 67 */ 63 68 64 69 /* Forward declarations of static functions. */ 65 static void *create_node(int); 66 static bool link_node(void *, void *, const char *); 67 static int unlink_node(void *); 68 static void destroy_node(void *); 70 static bool tmpfs_match(void *, const char *); 71 static void *tmpfs_create_node(int); 72 static bool tmpfs_link_node(void *, void *, const char *); 73 static int tmpfs_unlink_node(void *); 74 static void tmpfs_destroy_node(void *); 75 76 /* Implementation of helper functions. */ 77 static unsigned long tmpfs_index_get(void *nodep) 78 { 79 return ((tmpfs_dentry_t *) nodep)->index; 80 } 81 82 static unsigned long tmpfs_size_get(void *nodep) 83 { 84 return ((tmpfs_dentry_t *) nodep)->size; 85 } 86 87 static unsigned tmpfs_lnkcnt_get(void *nodep) 88 { 89 return 1; 90 } 91 92 static void *tmpfs_child_get(void *nodep) 93 { 94 return ((tmpfs_dentry_t *) nodep)->child; 95 } 96 97 static void *tmpfs_sibling_get(void *nodep) 98 { 99 return ((tmpfs_dentry_t *) nodep)->sibling; 100 } 101 102 static void *tmpfs_root_get(void) 103 { 104 return root; 105 } 106 107 static char tmpfs_plb_get_char(unsigned pos) 108 { 109 return tmpfs_reg.plb_ro[pos % PLB_SIZE]; 110 } 111 112 static bool tmpfs_is_directory(void *nodep) 113 { 114 return ((tmpfs_dentry_t *) nodep)->type == TMPFS_DIRECTORY; 115 } 116 117 static bool tmpfs_is_file(void *nodep) 118 { 119 return ((tmpfs_dentry_t *) nodep)->type == TMPFS_FILE; 120 } 121 122 /** libfs operations */ 123 libfs_ops_t tmpfs_libfs_ops = { 124 .match = tmpfs_match, 125 .create = tmpfs_create_node, 126 .destroy = tmpfs_destroy_node, 127 .link = tmpfs_link_node, 128 .unlink = tmpfs_unlink_node, 129 .index_get = tmpfs_index_get, 130 .size_get = tmpfs_size_get, 131 .lnkcnt_get = tmpfs_lnkcnt_get, 132 .child_get = tmpfs_child_get, 133 .sibling_get = tmpfs_sibling_get, 134 .root_get = tmpfs_root_get, 135 .plb_get_char = tmpfs_plb_get_char, 136 .is_directory = tmpfs_is_directory, 137 .is_file = tmpfs_is_file 138 }; 69 139 70 140 /** Hash table of all directory entries. */ 71 141 hash_table_t dentries; 72 142 143 /* Implementation of hash table interface. */ 73 144 static hash_index_t dentries_hash(unsigned long *key) 74 145 { … … 110 181 } 111 182 112 /*113 * For now, we don't distinguish between different dev_handles/instances. All114 * requests resolve to the only instance, rooted in the following variable.115 */116 static tmpfs_dentry_t *root;117 118 183 static bool tmpfs_init(void) 119 184 { 120 185 if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops)) 121 186 return false; 122 root = (tmpfs_dentry_t *) create_node(L_DIRECTORY);187 root = (tmpfs_dentry_t *) tmpfs_create_node(L_DIRECTORY); 123 188 return root != NULL; 124 189 } … … 131 196 * @return True on match, false otherwise. 132 197 */ 133 static bool match_component(void *nodep, const char *component)198 bool tmpfs_match(void *nodep, const char *component) 134 199 { 135 200 tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) nodep; … … 138 203 } 139 204 140 void * create_node(int lflag)205 void *tmpfs_create_node(int lflag) 141 206 { 142 207 assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); … … 158 223 } 159 224 160 bool link_node(void *prnt, void *chld, const char *nm)225 bool tmpfs_link_node(void *prnt, void *chld, const char *nm) 161 226 { 162 227 tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt; … … 186 251 } 187 252 188 int unlink_node(void *nodeptr)253 int tmpfs_unlink_node(void *nodeptr) 189 254 { 190 255 tmpfs_dentry_t *dentry = (tmpfs_dentry_t *)nodeptr; … … 214 279 } 215 280 216 void destroy_node(void *nodep)281 void tmpfs_destroy_node(void *nodep) 217 282 { 218 283 tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) nodep; … … 231 296 void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request) 232 297 { 233 unsigned next = IPC_GET_ARG1(*request); 234 unsigned last = IPC_GET_ARG2(*request); 235 int dev_handle = IPC_GET_ARG3(*request); 236 int lflag = IPC_GET_ARG4(*request); 237 238 if (last < next) 239 last += PLB_SIZE; 240 241 /* 242 * Initialize TMPFS. 243 */ 298 /* Initialize TMPFS. */ 244 299 if (!root && !tmpfs_init()) { 245 300 ipc_answer_0(rid, ENOMEM); 246 301 return; 247 302 } 248 249 tmpfs_dentry_t *dtmp = root->child; 250 tmpfs_dentry_t *dcur = root; 251 252 if (PLB_GET_CHAR(next) == '/') 253 next++; /* eat slash */ 254 255 char component[NAME_MAX + 1]; 256 int len = 0; 257 while (dtmp && next <= last) { 258 259 /* collect the component */ 260 if (PLB_GET_CHAR(next) != '/') { 261 if (len + 1 == NAME_MAX) { 262 /* comopnent length overflow */ 263 ipc_answer_0(rid, ENAMETOOLONG); 264 return; 265 } 266 component[len++] = PLB_GET_CHAR(next); 267 next++; /* process next character */ 268 if (next <= last) 269 continue; 270 } 271 272 assert(len); 273 component[len] = '\0'; 274 next++; /* eat slash */ 275 len = 0; 276 277 /* match the component */ 278 while (dtmp && !match_component(dtmp, component)) 279 dtmp = dtmp->sibling; 280 281 /* handle miss: match amongst siblings */ 282 if (!dtmp) { 283 if ((next > last) && (lflag & L_CREATE)) { 284 /* no components left and L_CREATE specified */ 285 if (dcur->type != TMPFS_DIRECTORY) { 286 ipc_answer_0(rid, ENOTDIR); 287 return; 288 } 289 void *nodep = create_node(lflag); 290 if (nodep) { 291 if (!link_node(dcur, nodep, 292 component)) { 293 destroy_node(nodep); 294 ipc_answer_0(rid, ENOSPC); 295 } else { 296 ipc_answer_5(rid, EOK, 297 tmpfs_reg.fs_handle, 298 dev_handle, 299 TMPFS_GET_INDEX(nodep), 0, 300 TMPFS_GET_LNKCNT(nodep)); 301 } 302 } else { 303 ipc_answer_0(rid, ENOSPC); 304 } 305 return; 306 } 307 ipc_answer_0(rid, ENOENT); 308 return; 309 } 310 311 /* descend one level */ 312 dcur = dtmp; 313 dtmp = dtmp->child; 314 } 315 316 /* handle miss: excessive components */ 317 if (!dtmp && next <= last) { 318 if (lflag & L_CREATE) { 319 if (dcur->type != TMPFS_DIRECTORY) { 320 ipc_answer_0(rid, ENOTDIR); 321 return; 322 } 323 324 /* collect next component */ 325 while (next <= last) { 326 if (PLB_GET_CHAR(next) == '/') { 327 /* more than one component */ 328 ipc_answer_0(rid, ENOENT); 329 return; 330 } 331 if (len + 1 == NAME_MAX) { 332 /* component length overflow */ 333 ipc_answer_0(rid, ENAMETOOLONG); 334 return; 335 } 336 component[len++] = PLB_GET_CHAR(next); 337 next++; /* process next character */ 338 } 339 assert(len); 340 component[len] = '\0'; 341 len = 0; 342 343 void *nodep = create_node(lflag); 344 if (nodep) { 345 if (!link_node(dcur, nodep, component)) { 346 destroy_node(nodep); 347 ipc_answer_0(rid, ENOSPC); 348 } else { 349 ipc_answer_5(rid, EOK, 350 tmpfs_reg.fs_handle, 351 dev_handle, TMPFS_GET_INDEX(nodep), 352 0, TMPFS_GET_LNKCNT(nodep)); 353 } 354 } else { 355 ipc_answer_0(rid, ENOSPC); 356 } 357 return; 358 } 359 ipc_answer_0(rid, ENOENT); 360 return; 361 } 362 363 /* handle hit */ 364 if (lflag & L_DESTROY) { 365 unsigned old_lnkcnt = TMPFS_GET_LNKCNT(dcur); 366 int res = unlink_node(dcur); 367 ipc_answer_5(rid, (ipcarg_t)res, tmpfs_reg.fs_handle, 368 dev_handle, dcur->index, dcur->size, old_lnkcnt); 369 return; 370 } 371 if ((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) { 372 ipc_answer_0(rid, EEXIST); 373 return; 374 } 375 if ((lflag & L_FILE) && (dcur->type != TMPFS_FILE)) { 376 ipc_answer_0(rid, EISDIR); 377 return; 378 } 379 if ((lflag & L_DIRECTORY) && (dcur->type != TMPFS_DIRECTORY)) { 380 ipc_answer_0(rid, ENOTDIR); 381 return; 382 } 383 384 ipc_answer_5(rid, EOK, tmpfs_reg.fs_handle, dev_handle, dcur->index, 385 dcur->size, TMPFS_GET_LNKCNT(dcur)); 303 libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); 386 304 } 387 305 … … 562 480 tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, 563 481 dh_link); 564 destroy_node(dentry);482 tmpfs_destroy_node(dentry); 565 483 ipc_answer_0(rid, EOK); 566 484 }
Note:
See TracChangeset
for help on using the changeset viewer.