patch-2.4.10 linux/fs/ntfs/dir.c
Next file: linux/fs/ntfs/fs.c
Previous file: linux/fs/ntfs/attr.h
Back to the patch index
Back to the overall index
- Lines: 366
- Date:
Tue Sep 11 17:02:46 2001
- Orig file:
v2.4.9/linux/fs/ntfs/dir.c
- Orig date:
Mon Aug 27 12:41:46 2001
diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/dir.c linux/fs/ntfs/dir.c
@@ -27,8 +27,7 @@
* be restored. */
int ntfs_check_index_record(ntfs_inode *ino, char *record)
{
- return ntfs_fixup_record(ino->vol, record, "INDX",
- ino->u.index.recordsize);
+ return ntfs_fixup_record(record, "INDX", ino->u.index.recordsize);
}
static inline int ntfs_is_top(ntfs_u64 stack)
@@ -95,15 +94,15 @@
#endif
/* True if the entry points to another block of entries. */
-static inline int ntfs_entry_has_subnodes(char* entry)
+static inline int ntfs_entry_has_subnodes(char *entry)
{
- return (int)NTFS_GETU8(entry + 12) & 1;
+ return (NTFS_GETU16(entry + 0xc) & 1);
}
/* True if it is not the 'end of dir' entry. */
-static inline int ntfs_entry_is_used(char* entry)
+static inline int ntfs_entry_is_used(char *entry)
{
- return (int)(NTFS_GETU8(entry + 12) & 2) == 0;
+ return !(NTFS_GETU16(entry + 0xc) & 2);
}
/*
@@ -268,12 +267,21 @@
ntfs_resize_attr(walk->dir, a, used);
} else {
NTFS_PUTU16(buf + 0x1C, used - 0x18);
- ntfs_insert_fixups(buf, vol->sector_size);
io.size = walk->dir->u.index.recordsize;
+ error = ntfs_insert_fixups(buf, io.size);
+ if (error) {
+ printk(KERN_ALERT "NTFS: ntfs_index_writeback() caught "
+ "corrupt index record ntfs record "
+ "header. Refusing to write corrupt "
+ "data to disk. Unmount and run chkdsk "
+ "immediately!\n");
+ return -EIO;
+ }
error = ntfs_write_attr(walk->dir, vol->at_index_allocation,
- I30, (__s64)block << vol->cluster_size_bits, &io);
+ I30, (__s64)block << vol->cluster_size_bits,
+ &io);
if (error || (io.size != walk->dir->u.index.recordsize &&
- (error = -EIO, 1)))
+ (error = -EIO, 1)))
return error;
}
return 0;
@@ -422,7 +430,7 @@
ra = ntfs_find_attr(ino, ino->vol->at_index_root, I30);
if (!ra)
- return -E2BIG;
+ return -ENOTDIR;
bsize = ino->vol->mft_record_size;
root = ntfs_malloc(bsize);
if (!root)
@@ -467,7 +475,7 @@
NTFS_PUTU32(index + 0x24, NTFS_GETU32(root + 0x1C));
error = ntfs_index_writeback(&walk, index, walk.newblock,
isize + NTFS_GETU16(index + 0x18) + 0x18);
- if(error)
+ if (error)
goto out;
/* Mark root as split. */
NTFS_PUTU32(root + 0x1C, 1);
@@ -732,7 +740,7 @@
/* 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 ntfs_getdir(ntfs_iterate_s *walk)
{
int length = walk->dir->vol->mft_record_size;
int retval, error;
@@ -780,145 +788,190 @@
return ntfs_getdir(walk);
}
-int ntfs_getdir_unsorted(ntfs_inode *ino, ntfs_u32 *p_high, ntfs_u32* p_low,
- int (*cb)(ntfs_u8*, void*), void *param)
+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_io io;
- int length;
- int block;
- int start;
ntfs_attribute *attr;
ntfs_volume *vol;
- int byte, bit;
- int error = 0;
+ int byte, bit, err = 0;
+ u32 start, finish, ibs, max_size;
+ ntfs_io io;
+ u8 ibs_bits;
if (!ino) {
- ntfs_error("No inode passed to getdir_unsorted\n");
+ ntfs_error(__FUNCTION__ "(): No inode! Returning -EINVAL.\n");
return -EINVAL;
}
vol = ino->vol;
if (!vol) {
- ntfs_error("Inode %d has no volume\n", ino->i_number);
+ ntfs_error(__FUNCTION__ "(): Inode 0x%lx has no volume. "
+ "Returning -EINVAL.\n", ino->i_number);
return -EINVAL;
}
- ntfs_debug(DEBUG_DIR3, "unsorted 1\n");
- /* Are we still in the index root? */
- if (*p_high == 0) {
- buf = ntfs_malloc(length = vol->mft_record_size);
+ 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;
- io.size = length;
- error = ntfs_read_attr(ino, vol->at_index_root, I30, 0, &io);
- if (error) {
- ntfs_free(buf);
- return error;
- }
- ino->u.index.recordsize = NTFS_GETU32(buf + 0x8);
+ 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, "unsorted 2\n");
- } else { /* we are in an index record */
- length = ino->u.index.recordsize;
- buf = ntfs_malloc(length);
+ 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;
- io.size = length;
- /* 0 is index root, index allocation starts with 4. */
- block = *p_high - ino->u.index.clusters_per_record;
- error = ntfs_read_attr(ino, vol->at_index_allocation, I30,
- (__s64)block << vol->cluster_size_bits, &io);
- if (!error && io.size != length)
- error = -EIO;
- if (error) {
- ntfs_error("read failed\n");
- ntfs_free(buf);
- return error;
- }
+ /*
+ * 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("%x is not an index record\n", block);
+ 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 + NTFS_GETU16(buf + 0x18) + 0x18;
- ntfs_debug(DEBUG_DIR3, "unsorted 3\n");
+ entry = buf + 0x18 + NTFS_GETU16(buf + 0x18);
+ ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted 3: In index "
+ "allocation.\n");
+ start = 0;
}
/* Process the entries. */
- start = *p_low;
- while (ntfs_entry_is_used(entry)) {
- ntfs_debug(DEBUG_DIR3, "unsorted 4\n");
- if (start)
- start--; /* Skip entries that were already processed. */
- else {
- ntfs_debug(DEBUG_DIR3, "unsorted 5\n");
- if ((error = cb(entry, param)))
- /* The entry could not be processed. */
- break;
- (*p_low)++;
+ 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;
}
- entry += NTFS_GETU16(entry + 8);
- }
- ntfs_debug(DEBUG_DIR3, "unsorted 6\n");
- /* Caller did not process all entries. */
- if (error) {
- ntfs_free(buf);
- ntfs_debug(DEBUG_DIR3, "unsorted 7\n");
- return error;
+ 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 allocation. */
- *p_high = 0xFFFFFFFF;
- *p_low = 0;
- ntfs_debug(DEBUG_DIR3, "unsorted 8\n");
+ /* 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;
}
- buf = ntfs_malloc(length = attr->size);
+ 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 = length;
- error = ntfs_read_attr(ino, vol->at_bitmap, I30, 0, &io);
- if (!error && io.size != length)
- error = -EIO;
- if (error) {
- ntfs_free(buf);
- ntfs_debug(DEBUG_DIR3, "unsorted 9\n");
- return -EIO;
- }
+ 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, "unsorted 9.5\n");
+ 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 ((__s64)*p_high << vol->cluster_size_bits > attr->size) {
+ 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 = 0xFFFFFFFF;
+ *p_high = 0x7fff;
+ *p_low = 0;
ntfs_free(buf);
- ntfs_debug(DEBUG_DIR3, "unsorted 10\n");
+ ntfs_debug(DEBUG_DIR3, __FUNCTION__ "(): Unsorted "
+ "10.5: No more index records. "
+ "Returning 0, p_high 0x7fff, p_low "
+ "0.\n");
return 0;
}
- *p_high += ino->u.index.clusters_per_record;
- byte = *p_high / ino->u.index.clusters_per_record - 1;
+ byte = (ntfs_cluster_t)(*p_high - 1);
bit = 1 << (byte & 7);
- byte = byte >> 3;
- /* This record is allocated. */
- if (buf[byte] & bit)
+ byte >>= 3;
+ if ((buf[byte] & bit))
break;
- }
- ntfs_debug(DEBUG_DIR3, "unsorted 11\n");
+ };
+ 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)
@@ -1025,7 +1078,7 @@
data, sizeof(data), &da);
}
-int ntfs_mkdir(ntfs_inode* dir, const char* name, int namelen,
+int ntfs_mkdir(ntfs_inode *dir, const char *name, int namelen,
ntfs_inode *result)
{
int error;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)