📄 dir.c
字号:
INDEX_TYPE_ROOT, ir, ie, dirent, filldir); if (rc) { ntfs_attr_put_search_ctx(ctx); ctx = NULL; goto err_out; } } ntfs_attr_put_search_ctx(ctx); ctx = NULL; /* If there is no index allocation attribute we are finished. */ if (!ia_na) goto EOD; /* Advance *pos to the beginning of the index allocation. */ *pos = vol->mft_record_size;skip_index_root: if (!ia_na) goto done; /* Allocate a buffer for the current index block. */ ia = ntfs_malloc(index_block_size); if (!ia) goto err_out; bmp_na = ntfs_attr_open(dir_ni, AT_BITMAP, NTFS_INDEX_I30, 4); if (!bmp_na) { ntfs_log_perror("Failed to open index bitmap attribute"); goto dir_err_out; } /* Get the offset into the index allocation attribute. */ ia_pos = *pos - vol->mft_record_size; bmp_pos = ia_pos >> index_block_size_bits; if (bmp_pos >> 3 >= bmp_na->data_size) { ntfs_log_error("Current index position exceeds index bitmap " "size.\n"); goto dir_err_out; } bmp_buf_size = min(bmp_na->data_size - (bmp_pos >> 3), 4096); bmp = ntfs_malloc(bmp_buf_size); if (!bmp) goto err_out; br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp); if (br != bmp_buf_size) { if (br != -1) errno = EIO; ntfs_log_perror("Failed to read from index bitmap attribute"); goto err_out; } bmp_buf_pos = 0; /* If the index block is not in use find the next one that is. */ while (!(bmp[bmp_buf_pos >> 3] & (1 << (bmp_buf_pos & 7)))) {find_next_index_buffer: bmp_pos++; bmp_buf_pos++; /* If we have reached the end of the bitmap, we are done. */ if (bmp_pos >> 3 >= bmp_na->data_size) goto EOD; ia_pos = bmp_pos << index_block_size_bits; if (bmp_buf_pos >> 3 < bmp_buf_size) continue; /* Read next chunk from the index bitmap. */ bmp_buf_pos = 0; if ((bmp_pos >> 3) + bmp_buf_size > bmp_na->data_size) bmp_buf_size = bmp_na->data_size - (bmp_pos >> 3); br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp); if (br != bmp_buf_size) { if (br != -1) errno = EIO; ntfs_log_perror("Failed to read from index bitmap attribute"); goto err_out; } } ntfs_log_debug("Handling index block 0x%llx.\n", (long long)bmp_pos); /* Read the index block starting at bmp_pos. */ br = ntfs_attr_mst_pread(ia_na, bmp_pos << index_block_size_bits, 1, index_block_size, ia); if (br != 1) { if (br != -1) errno = EIO; ntfs_log_perror("Failed to read index block"); goto err_out; } ia_start = ia_pos & ~(s64)(index_block_size - 1); if (sle64_to_cpu(ia->index_block_vcn) != ia_start >> index_vcn_size_bits) { ntfs_log_error("Actual VCN (0x%llx) of index buffer is different " "from expected VCN (0x%llx) in inode 0x%llx.\n", (long long)sle64_to_cpu(ia->index_block_vcn), (long long)ia_start >> index_vcn_size_bits, (unsigned long long)dir_ni->mft_no); goto dir_err_out; } if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) { ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode 0x%llx " "has a size (%u) differing from the directory " "specified size (%u).\n", (long long)ia_start >> index_vcn_size_bits, (unsigned long long)dir_ni->mft_no, (unsigned) le32_to_cpu(ia->index.allocated_size) + 0x18, (unsigned)index_block_size); goto dir_err_out; } index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); if (index_end > (u8*)ia + index_block_size) { ntfs_log_error("Size of index buffer (VCN 0x%llx) of directory inode " "0x%llx exceeds maximum size.\n", (long long)ia_start >> index_vcn_size_bits, (unsigned long long)dir_ni->mft_no); goto dir_err_out; } /* The first index entry. */ ie = (INDEX_ENTRY*)((u8*)&ia->index + le32_to_cpu(ia->index.entries_offset)); /* * Loop until we exceed valid memory (corruption case) or until we * reach the last entry or until ntfs_filldir tells us it has had * enough or signals an error (both covered by the rc test). */ for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { ntfs_log_debug("In index allocation, offset 0x%llx.\n", (long long)ia_start + ((u8*)ie - (u8*)ia)); /* Bounds checks. */ if ((u8*)ie < (u8*)ia || (u8*)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || (u8*)ie + le16_to_cpu(ie->key_length) > index_end) { ntfs_log_error("Index entry out of bounds in directory inode " "0x%llx.\n", (unsigned long long)dir_ni->mft_no); goto dir_err_out; } /* The last entry cannot contain a name. */ if (ie->ie_flags & INDEX_ENTRY_END) break; /* Skip index entry if continuing previous readdir. */ if (ia_pos - ia_start > (u8*)ie - (u8*)ia) continue; /* * Submit the directory entry to ntfs_filldir(), which will * invoke the filldir() callback as appropriate. */ rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits, INDEX_TYPE_ALLOCATION, ia, ie, dirent, filldir); if (rc) goto err_out; } goto find_next_index_buffer;EOD: /* We are finished, set *pos to EOD. */ *pos = i_size + vol->mft_record_size;done: free(ia); free(bmp); if (bmp_na) ntfs_attr_close(bmp_na); if (ia_na) ntfs_attr_close(ia_na); ntfs_log_debug("EOD, *pos 0x%llx, returning 0.\n", (long long)*pos); return 0;dir_err_out: errno = EIO;err_out: eo = errno; ntfs_log_trace("failed.\n"); if (ctx) ntfs_attr_put_search_ctx(ctx); free(ia); free(bmp); if (bmp_na) ntfs_attr_close(bmp_na); if (ia_na) ntfs_attr_close(ia_na); errno = eo; return -1;}/** * __ntfs_create - create object on ntfs volume * @dir_ni: ntfs inode for directory in which create new object * @name: unicode name of new object * @name_len: length of the name in unicode characters * @type: type of the object to create * @dev: major and minor device numbers (obtained from makedev()) * @target: target in unicode (only for symlinks) * @target_len: length of target in unicode characters * * Internal, use ntfs_create{,_device,_symlink} wrappers instead. * * @type can be: * S_IFREG to create regular file * S_IFDIR to create directory * S_IFBLK to create block device * S_IFCHR to create character device * S_IFLNK to create symbolic link * S_IFIFO to create FIFO * S_IFSOCK to create socket * other values are invalid. * * @dev is used only if @type is S_IFBLK or S_IFCHR, in other cases its value * ignored. * * @target and @target_len are used only if @type is S_IFLNK, in other cases * their value ignored. * * Return opened ntfs inode that describes created object on success or NULL * on error with errno set to the error code. */static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, dev_t type, dev_t dev, ntfschar *target, int target_len){ ntfs_inode *ni; int rollback_data = 0, rollback_sd = 0; FILE_NAME_ATTR *fn = NULL; STANDARD_INFORMATION *si = NULL; int err, fn_len, si_len; ntfs_log_trace("Entering.\n"); /* Sanity checks. */ if (!dir_ni || !name || !name_len) { ntfs_log_error("Invalid arguments.\n"); errno = EINVAL; return NULL; } if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) { errno = EOPNOTSUPP; return NULL; } ni = ntfs_mft_record_alloc(dir_ni->vol, NULL); if (!ni) return NULL; /* * Create STANDARD_INFORMATION attribute. Write STANDARD_INFORMATION * version 1.2, windows will upgrade it to version 3 if needed. */ si_len = offsetof(STANDARD_INFORMATION, v1_end); si = ntfs_calloc(si_len); if (!si) { err = errno; goto err_out; } si->creation_time = utc2ntfs(ni->creation_time); si->last_data_change_time = utc2ntfs(ni->last_data_change_time); si->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); si->last_access_time = utc2ntfs(ni->last_access_time); if (!S_ISREG(type) && !S_ISDIR(type)) { si->file_attributes = FILE_ATTR_SYSTEM; ni->flags = FILE_ATTR_SYSTEM; } /* Add STANDARD_INFORMATION to inode. */ if (ntfs_attr_add(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, (u8*)si, si_len)) { err = errno; ntfs_log_error("Failed to add STANDARD_INFORMATION " "attribute.\n"); goto err_out; } if (ntfs_sd_add_everyone(ni)) { err = errno; goto err_out; } rollback_sd = 1; if (S_ISDIR(type)) { INDEX_ROOT *ir = NULL; INDEX_ENTRY *ie; int ir_len, index_len; /* Create INDEX_ROOT attribute. */ index_len = sizeof(INDEX_HEADER) + sizeof(INDEX_ENTRY_HEADER); ir_len = offsetof(INDEX_ROOT, index) + index_len; ir = ntfs_calloc(ir_len); if (!ir) { err = errno; goto err_out; } ir->type = AT_FILE_NAME; ir->collation_rule = COLLATION_FILE_NAME; ir->index_block_size = cpu_to_le32(ni->vol->indx_record_size); if (ni->vol->cluster_size <= ni->vol->indx_record_size) ir->clusters_per_index_block = ni->vol->indx_record_size >> ni->vol->cluster_size_bits; else ir->clusters_per_index_block = ni->vol->indx_record_size >> ni->vol->sector_size_bits; ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER)); ir->index.index_length = cpu_to_le32(index_len); ir->index.allocated_size = cpu_to_le32(index_len); ie = (INDEX_ENTRY*)((u8*)ir + sizeof(INDEX_ROOT)); ie->length = cpu_to_le16(sizeof(INDEX_ENTRY_HEADER)); ie->key_length = 0; ie->ie_flags = INDEX_ENTRY_END; /* Add INDEX_ROOT attribute to inode. */ if (ntfs_attr_add(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4, (u8*)ir, ir_len)) { err = errno; free(ir); ntfs_log_error("Failed to add INDEX_ROOT attribute.\n"); goto err_out; } free(ir); } else { INTX_FILE *data; int data_len; switch (type) { case S_IFBLK: case S_IFCHR: data_len = offsetof(INTX_FILE, device_end); data = ntfs_malloc(data_len); if (!data) { err = errno; goto err_out; } data->major = cpu_to_le64(major(dev)); data->minor = cpu_to_le64(minor(dev)); if (type == S_IFBLK) data->magic = INTX_BLOCK_DEVICE; if (type == S_IFCHR) data->magic = INTX_CHARACTER_DEVICE; break; case S_IFLNK: data_len = sizeof(INTX_FILE_TYPES) + target_len * sizeof(ntfschar); data = ntfs_malloc(data_len); if (!data) { err = errno; goto err_out; } data->magic = INTX_SYMBOLIC_LINK; memcpy(data->target, target, target_len * sizeof(ntfschar)); break; case S_IFSOCK: data = NULL; data_len = 1; break; default: /* FIFO or regular file. */ data = NULL; data_len = 0; break; } /* Add DATA attribute to inode. */ if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, (u8*)data, data_len)) { err = errno; ntfs_log_error("Failed to add DATA attribute.\n"); free(data); goto err_out; } rollback_data = 1; free(data); } /* Create FILE_NAME attribute. */ fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); fn = ntfs_calloc(fn_len); if (!fn) { err = errno; goto err_out; } fn->parent_directory = MK_LE_MREF(dir_ni->mft_no, le16_to_cpu(dir_ni->mrec->sequence_number)); fn->file_name_length = name_len; fn->file_name_type = FILE_NAME_POSIX; if (S_ISDIR(type)) fn->file_attributes = FILE_ATTR_I30_INDEX_PRESENT; if (!S_ISREG(type) && !S_ISDIR(type)) fn->file_attributes = FILE_ATTR_SYSTEM; fn->creation_time = utc2ntfs(ni->creation_time); fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); fn->last_access_time = utc2ntfs(ni->last_access_time); fn->data_size = cpu_to_sle64(ni->data_size); fn->allocated_size = cpu_to_sle64(ni->allocated_size); memcpy(fn->file_name, name, name_len * sizeof(ntfschar)); /* Add FILE_NAME attribute to inode. */ if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) { err = errno; ntfs_log_error("Failed to add FILE_NAME attribute.\n"); goto err_out; } /* Add FILE_NAME attribute to index. */ if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number)))) { err = errno; ntfs_log_perror("Failed to add entry to the index"); goto err_out; } /* Set hard links count and directory flag. */ ni->mrec->link_count = cpu_to_le16(1); if (S_ISDIR(type)) ni->mrec->flags |= MFT_RECORD_IS_DIRECTORY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -