📄 dir.c
字号:
* More values are hopefully not needed, as the file position has currently * 64 bits in total. *//* Find an entry in the directory. Return 0 if not found, otherwise copy the * entry to the result buffer. */int ntfs_getdir(ntfs_iterate_s *walk){ int length = walk->dir->vol->mft_record_size; int retval, error; /* Start at the index root. */ char *root = ntfs_malloc(length); ntfs_io io; if (!root) return -ENOMEM; io.fn_put = ntfs_put; io.param = root; io.size = length; error = ntfs_read_attr(walk->dir, walk->dir->vol->at_index_root, I30, 0, &io); if (error) { ntfs_error("Not a directory\n"); return 0; } walk->block = -1; /* FIXME: Move these to walk. */ walk->dir->u.index.recordsize = NTFS_GETU32(root + 0x8); walk->dir->u.index.clusters_per_record = NTFS_GETU32(root + 0xC); /* FIXME: Consistency check. */ /* Skip header. */ retval = ntfs_getdir_iterate(walk, root, root + 0x20); ntfs_free(root); return retval;}/* Find an entry in the directory by its position stack. Iteration starts * if the stack is 0, in which case the position is set to the first item * in the directory. If the position is nonzero, return the item at the * position and change the position to the next item. The position is -1 * if there are no more items. */int ntfs_getdir_byposition(ntfs_iterate_s *walk){ walk->type = BY_POSITION; return ntfs_getdir(walk);}/* Find an entry in the directory by its name. Return 0 if not found. */int ntfs_getdir_byname(ntfs_iterate_s *walk){ walk->type = BY_NAME; return ntfs_getdir(walk);}int ntfs_getdir_unsorted(ntfs_inode *ino, u32 *p_high, u32 *p_low, int (*cb)(ntfs_u8 *, void *), void *param){ s64 ib_ofs; char *buf = 0, *entry = 0; ntfs_attribute *attr; ntfs_volume *vol; int byte, bit, err = 0; u32 start, finish, ibs, max_size; ntfs_io io; u8 ibs_bits; if (!ino) { ntfs_error(__FUNCTION__ "(): No inode! Returning -EINVAL.\n"); return -EINVAL; } vol = ino->vol; if (!vol) { ntfs_error(__FUNCTION__ "(): Inode 0x%lx has no volume. " "Returning -EINVAL.\n", ino->i_number); return -EINVAL; } ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 1: Entering for " "inode 0x%lx, p_high = 0x%x, p_low = 0x%x.\n", ino->i_number, *p_high, *p_low); if (!*p_high) { /* We are still in the index root. */ buf = ntfs_malloc(io.size = vol->mft_record_size); if (!buf) return -ENOMEM; io.fn_put = ntfs_put; io.param = buf; err = ntfs_read_attr(ino, vol->at_index_root, I30, 0, &io); if (err || !io.size) goto read_err_ret; ino->u.index.recordsize = ibs = NTFS_GETU32(buf + 0x8); ino->u.index.clusters_per_record = NTFS_GETU32(buf + 0xC); entry = buf + 0x20; ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 2: In index " "root.\n"); ibs_bits = ffs(ibs) - 1; /* Compensate for faked "." and "..". */ start = 2; } else { /* We are in an index record. */ io.size = ibs = ino->u.index.recordsize; buf = ntfs_malloc(ibs); if (!buf) return -ENOMEM; ibs_bits = ffs(ibs) - 1; io.fn_put = ntfs_put; io.param = buf; /* * 0 is index root, index allocation starts at 1 and works in * units of index block size (ibs). */ ib_ofs = (s64)(*p_high - 1) << ibs_bits; err = ntfs_read_attr(ino, vol->at_index_allocation, I30, ib_ofs, &io); if (err || io.size != ibs) goto read_err_ret; if (!ntfs_check_index_record(ino, buf)) { ntfs_error(__FUNCTION__ "(): Index block 0x%x is not " "an index record. Returning " "-ENOTDIR.\n", *p_high - 1); ntfs_free(buf); return -ENOTDIR; } entry = buf + 0x18 + NTFS_GETU16(buf + 0x18); ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 3: In index " "allocation.\n"); start = 0; } /* Process the entries. */ finish = *p_low; for (; entry < (buf + ibs) && ntfs_entry_is_used(entry); entry += NTFS_GETU16(entry + 8)) { if (start < finish) { /* Skip entries that were already processed. */ ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 4: " "Skipping already processed entry " "p_high 0x%x, p_low 0x%x.\n", *p_high, start); start++; continue; } ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 5: " "Processing entry p_high 0x%x, p_low 0x%x.\n", *p_high, *p_low); if ((err = cb(entry, param))) { /* filldir signalled us to stop. */ ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): " "Unsorted 6: cb returned %i, " "returning 0, p_high 0x%x, p_low 0x%x." "\n", *p_high, *p_low); ntfs_free(buf); return 0; } ++*p_low; } ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 7: After processing " "entries, p_high 0x%x, p_low 0x%x.\n", *p_high, *p_low); /* We have to locate the next record. */ ntfs_free(buf); buf = 0; *p_low = 0; attr = ntfs_find_attr(ino, vol->at_bitmap, I30); if (!attr) { /* Directory does not have index bitmap and index allocation. */ *p_high = 0x7fff; ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 8: No index " "allocation. Returning 0, p_high 0x7fff, " "p_low 0x0.\n"); return 0; } max_size = attr->size; if (max_size > 0x7fff >> 3) { ntfs_error(__FUNCTION__ "(): Directory too large. Visible " "length is truncated.\n"); max_size = 0x7fff >> 3; } buf = ntfs_malloc(max_size); if (!buf) return -ENOMEM; io.param = buf; io.size = max_size; err = ntfs_read_attr(ino, vol->at_bitmap, I30, 0, &io); if (err || io.size != max_size) goto read_err_ret; attr = ntfs_find_attr(ino, vol->at_index_allocation, I30); if (!attr) { ntfs_free(buf); ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 9: Find " "attr failed. Returning -EIO.\n"); return -EIO; } if (attr->resident) { ntfs_free(buf); ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 9.5: IA is " "resident. Not allowed. Returning EINVAL.\n"); return -EINVAL; } /* Loop while going through non-allocated index records. */ max_size <<= 3; while (1) { if (++*p_high >= 0x7fff) { ntfs_error(__FUNCTION__ "(): Unsorted 10: Directory " "inode 0x%lx overflowed the maximum " "number of index allocation buffers " "the driver can cope with. Pretending " "to be at end of directory.\n", ino->i_number); goto fake_eod; } if (*p_high > max_size || (s64)*p_high << ibs_bits > attr->initialized) {fake_eod: /* No more index records. */ *p_high = 0x7fff; *p_low = 0; ntfs_free(buf); ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted " "10.5: No more index records. " "Returning 0, p_high 0x7fff, p_low " "0.\n"); return 0; } byte = (ntfs_cluster_t)(*p_high - 1); bit = 1 << (byte & 7); byte >>= 3; if ((buf[byte] & bit)) break; }; ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 11: Done. " "Returning 0, p_high 0x%x, p_low 0x%x.\n", *p_high, *p_low); ntfs_free(buf); return 0;read_err_ret: if (!err) err = -EIO; ntfs_error(__FUNCTION__ "(): Read failed. Returning error code %i.\n", err); ntfs_free(buf); return err;}int ntfs_dir_add(ntfs_inode *dir, ntfs_inode *new, ntfs_attribute *name){ ntfs_iterate_s walk; int nsize, esize; ntfs_u8* entry, *ndata; int error; walk.type = DIR_INSERT; walk.dir = dir; walk.u.flags = 0; nsize = name->size; ndata = name->d.data; walk.name = (ntfs_u16*)(ndata + 0x42); walk.namelen = NTFS_GETU8(ndata + 0x40); walk.new_entry_size = esize = (nsize + 0x10 + 7) & ~7; walk.new_entry = entry = ntfs_malloc(esize); if (!entry) return -ENOMEM; NTFS_PUTINUM(entry, new); NTFS_PUTU16(entry + 0x8, esize); /* Size of entry. */ NTFS_PUTU16(entry + 0xA, nsize); /* Size of original name attribute. */ NTFS_PUTU16(entry + 0xC, 0); /* Flags. */ NTFS_PUTU16(entry + 0xE, 0); /* Reserved. */ ntfs_memcpy(entry + 0x10, ndata, nsize); ntfs_bzero(entry + 0x10 + nsize, esize - 0x10 - nsize); error = ntfs_getdir(&walk); if (walk.new_entry) ntfs_free(walk.new_entry); return error;}#if 0int ntfs_dir_add1(ntfs_inode *dir, const char* name, int namelen, ntfs_inode *ino){ ntfs_iterate_s walk; int error; int nsize; char *entry; ntfs_attribute *name_attr; error = ntfs_decodeuni(dir->vol, name, namelen, &walk.name, &walk.namelen); if (error) return error; /* FIXME: Set flags. */ walk.type = DIR_INSERT; walk.dir = dir; /* walk.new = ino; */ /* Prepare new entry. */ /* Round up to a multiple of 8. */ walk.new_entry_size = nsize = ((0x52 + 2 * walk.namelen + 7) / 8) * 8; walk.new_entry = entry = ntfs_malloc(nsize); if (!entry) return -ENOMEM; ntfs_bzero(entry, nsize); NTFS_PUTINUM(entry, ino); NTFS_PUTU16(entry + 8, nsize); NTFS_PUTU16(entry + 0xA, 0x42 + 2 * namelen); /* FIXME: Size of name * attribute. */ NTFS_PUTU32(entry + 0xC, 0); /* FIXME: D-F? */ name_attr = ntfs_find_attr(ino, vol->at_file_name, 0); /* FIXME: multiple names */ if (!name_attr || !name_attr->resident) return -EIDRM; /* Directory, file stamps, sizes, filename. */ ntfs_memcpy(entry + 0x10, name_attr->d.data, 0x42 + 2 * namelen); error = ntfs_getdir(&walk); ntfs_free(walk.name); return error;}#endif/* Fills out and creates an INDEX_ROOT attribute. */int ntfs_add_index_root(ntfs_inode *ino, int type){ ntfs_attribute *da; ntfs_u8 data[0x30]; /* 0x20 header, 0x10 last entry. */ char name[10]; NTFS_PUTU32(data, type); /* Collation rule. 1 == COLLATION_FILENAME */ NTFS_PUTU32(data + 4, 1); NTFS_PUTU32(data + 8, ino->vol->index_record_size); NTFS_PUTU32(data + 0xC, ino->vol->index_clusters_per_record); /* Byte offset to first INDEX_ENTRY. */ NTFS_PUTU32(data + 0x10, 0x10); /* Size of entries, including header. */ NTFS_PUTU32(data + 0x14, 0x20); NTFS_PUTU32(data + 0x18, 0x20); /* No index allocation, yet. */ NTFS_PUTU32(data + 0x1C, 0); /* Add last entry. */ /* Indexed MFT record. */ NTFS_PUTU64(data + 0x20, 0); /* Size of entry. */ NTFS_PUTU32(data + 0x28, 0x10); /* Flags: Last entry, no child nodes. */ NTFS_PUTU32(data + 0x2C, 2); /* Compute name. */ ntfs_indexname(name, type); return ntfs_create_attr(ino, ino->vol->at_index_root, name, data, sizeof(data), &da);}int ntfs_mkdir(ntfs_inode *dir, const char *name, int namelen, ntfs_inode *result){ int error; error = ntfs_alloc_inode(dir, result, name, namelen, NTFS_AFLAG_DIR); if (error) goto out; error = ntfs_add_index_root(result, 0x30); if (error) goto out; /* Set directory bit. */ result->attr[0x16] |= 2; error = ntfs_update_inode(dir); if (error) goto out; error = ntfs_update_inode(result); if (error) goto out; out: return error;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -