📄 dir40.c
字号:
{ /* Removing body item. */ if (obj40_update_body(dir, dir40_entry_comp) == PRESENT) { body_hint.count = 1; body_hint.place_func = NULL; body_hint.region_func = NULL; dir->body.pos.unit = MAX_UINT32; obj40_remove(dir, &dir->body, &body_hint); } return res; } return 0;}/* Removes all directory body items. */static errno_t dir40_mkempty(reiser4_object_t *dir, uint64_t n) { errno_t res; reiser4_key_t key; aal_assert("umka-1925", dir != NULL); /* Making sure, that dir->body points to correct item */ if ((res = obj40_update_body(dir, dir40_entry_comp)) != PRESENT) return res == ABSENT ? 0 : res; /* Creating maximal possible key in order to find last directory item and remove it from the tree. Thanks to Nikita for this idea. */ aal_memcpy(&key, &dir->body.key, sizeof(key)); objcall(&key, set_offset, MAX_UINT64); while (1) { trans_hint_t hint; /* Looking for the last directory item. FIXME: the possible speedup here is to get rid of lookup */ if ((res = obj40_find_item(dir, &key, FIND_EXACT, NULL, NULL, &dir->body)) < 0) { return res; } /* Checking if found item belongs this directory */ if (obj40_belong(&dir->body, &key) == ABSENT) return 0; aal_memset(&hint, 0, sizeof(hint)); hint.count = 1; hint.shift_flags = SF_DEFAULT; dir->body.pos.unit = MAX_UINT32; /* Removing item from the tree */ if ((res = obj40_remove(dir, &dir->body, &hint))) return res; } return 0;}/* Removes directory body and stat data from the tree. */static errno_t dir40_clobber(reiser4_object_t *dir) { uint32_t nlink; errno_t res; aal_assert("umka-2298", dir != NULL); /* Check that truncate is allowed -- i.e. nlink == 2. */ if ((nlink = obj40_get_nlink(dir, 1)) != 2) { aal_error("Can't detach the object " "with nlink (%d).", nlink); return -EINVAL; } dir40_reset(dir); /* Truncates directory body. */ if ((res = dir40_mkempty(dir, 0))) return res; /* Cloberring stat data. */ return obj40_clobber(dir);}/* Return number of hard links. */static bool_t dir40_linked(reiser4_object_t *dir) { return obj40_get_nlink(dir, 1) != 1;}/* Helper function. Builds @entry->offset key by @entry->name. */static errno_t dir40_build_entry(reiser4_object_t *dir, entry_hint_t *entry){ aal_assert("umka-2528", entry != NULL); aal_assert("umka-2527", dir != NULL); plugcall(dir->info.object.plug, build_hashed, &entry->offset, reiser4_pshash(dir), reiser4_psfibre(dir), objcall(&dir->info.object, get_locality), objcall(&dir->info.object, get_objectid), entry->name); return 0;}/* Add new entry to directory. */static errno_t dir40_add_entry(reiser4_object_t *dir, entry_hint_t *entry){ errno_t res; entry_hint_t temp; trans_hint_t hint; aal_assert("umka-844", dir != NULL); aal_assert("umka-845", entry != NULL); aal_memset(&hint, 0, sizeof(hint)); /* Getting place new entry will be inserted at. */ switch (dir40_search(dir, entry->name, FIND_EXACT, &temp)) { case ABSENT: if (!obj40_valid_item(&temp.place)) return -EINVAL; if ((res = obj40_fetch_item(&temp.place))) return res; break; case PRESENT: aal_error("Entry \"%s\" already exists.", entry->name); default: return -EINVAL; } /* Prepare trans hint. */ hint.count = 1; hint.region_func = NULL; hint.place_func = entry->place_func; hint.data = entry->data; hint.plug = temp.place.plug; hint.specific = (void *)entry; hint.shift_flags = SF_DEFAULT; /* Building key of the new entry and hint's one */ dir40_build_entry(dir, entry); /* Copying key to @hint */ aal_memcpy(&hint.offset, &entry->offset, sizeof(hint.offset)); /* Inserting entry described by @hint to tree at @temp.place */ if ((res = obj40_insert(dir, &temp.place, &hint, LEAF_LEVEL)) < 0) { return res; } entry->len = hint.len; /* Updating stat data fields. */ return obj40_touch(dir, 1, hint.bytes);}/* Removing entry from the directory */static errno_t dir40_rem_entry(reiser4_object_t *dir, entry_hint_t *entry){ errno_t res; entry_hint_t temp; trans_hint_t hint; aal_assert("umka-1923", entry != NULL); aal_assert("umka-1922", dir != NULL); aal_assert("umka-2390", entry->name != NULL); /* Looking for place to insert directory entry */ if (dir40_search(dir, entry->name, FIND_EXACT, &temp) != PRESENT) return -EINVAL; aal_memset(&hint, 0, sizeof(hint)); hint.count = 1; hint.shift_flags = SF_DEFAULT; /* Removing one unit from directory */ if ((res = obj40_remove(dir, &dir->body, &hint))) return res; if (!objcall(&dir->position, compfull, &temp.offset)) { if (entry->offset.adjust < dir->position.adjust) dir->position.adjust--; } entry->len = hint.len; /* Updating stat data fields */ return obj40_touch(dir, -1, -hint.bytes);}/* Attaches the given directory @dir to @parent object. */static errno_t dir40_attach(reiser4_object_t *dir, reiser4_object_t *parent){ errno_t res; entry_hint_t entry; aal_assert("umka-2289", dir != NULL); aal_assert("umka-2359", parent != NULL); aal_memset(&entry, 0, sizeof(entry)); aal_strncpy(entry.name, "..", sizeof(entry.name)); /* Adding ".." pointing to parent to @dir object. */ aal_memcpy(&entry.object, &parent->info.object, sizeof(entry.object)); if ((res = dir40_add_entry(dir, &entry))) return res; /* Increasing parent's @nlink by one */ return plugcall(reiser4_psobj(parent), link, parent);}/* Detaches @dir from @parent. */static errno_t dir40_detach(reiser4_object_t *dir, reiser4_object_t *parent){ entry_hint_t entry; errno_t res; aal_assert("umka-2291", dir != NULL); /* Removing ".." from child if it is found */ if (dir40_lookup(dir, "..", &entry) == PRESENT) { if ((res = dir40_rem_entry(dir, &entry))) return res; } if (!parent) return 0; /* Decreasing parent's @nlink by one */ return plugcall(reiser4_psobj(parent), unlink, parent);}/* This fucntion implements hashed directory enumerator function. It is used for calculating fargmentation, prining. */static errno_t dir40_layout(reiser4_object_t *dir, region_func_t func, void *data){ dir40_reset(dir); return obj40_layout(dir, func, dir40_entry_comp, data);}/* This fucntion implements hashed directory metadata enumerator function. This is needed for getting directory metadata for pack them, etc. */static errno_t dir40_metadata(reiser4_object_t *dir, place_func_t place_func, void *data){ dir40_reset(dir); return obj40_traverse(dir, place_func, dir40_entry_comp, data);}#endif/* Directory object operations. */reiser4_object_plug_t dir40_plug = { .p = { .id = {OBJECT_DIR40_ID, DIR_OBJECT, OBJECT_PLUG_TYPE},#ifndef ENABLE_MINIMAL .label = "dir40", .desc = "Directory file plugin.",#endif },#ifndef ENABLE_MINIMAL .inherit = obj40_inherit, .create = dir40_create, .layout = dir40_layout, .metadata = dir40_metadata, .link = obj40_link, .unlink = obj40_unlink, .linked = dir40_linked, .truncate = NULL, .add_entry = dir40_add_entry, .rem_entry = dir40_rem_entry, .build_entry = dir40_build_entry, .attach = dir40_attach, .detach = dir40_detach, .clobber = dir40_clobber, .recognize = obj40_recognize, .fake = dir40_fake, .check_struct = dir40_check_struct, .check_attach = dir40_check_attach, .seek = NULL, .write = NULL, .convert = NULL,#endif .follow = NULL, .read = NULL, .offset = NULL, .stat = obj40_load_stat, .open = obj40_open, .close = NULL, .reset = dir40_reset, .lookup = dir40_lookup, .seekdir = dir40_seekdir, .readdir = dir40_readdir, .telldir = dir40_telldir,#ifndef ENABLE_MINIMAL .sdext_mandatory = (1 << SDEXT_LW_ID), .sdext_unknown = (1 << SDEXT_SYMLINK_ID)#endif};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -