libext2fs: provide functions to safely access name_len and file_type

Accessing name_len (and file_type) in ext4_dir_entry structure is
somewhat problematic because on big endian architecture we need to now
whether we are really dealing with ext4_dir_entry (which has u16
name_len which needs byte swapping) or ext4_dir_entry_2 (which has u8
name_len which must not be byte swapped).

Currently the code is somewhat surprising and name_len is always
treated as u16 and byte swapped (flag EXT2_DIRBLOCK_V2_STRUCT isn't
ever used) and then masking of name_len is used to access real
name_len or file_type. Doing things this way in applications using
libext2fs is unexpected to say the least (more natural is to type
struct ext4_dir_entry * to struct ext4_dir_entry_2 * but that gives
wrong results on big endian architectures. So provide helper functions
that give endian-safe access to these fields. Also convert users in
e2fsprogs to use these functions.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
pu
Jan Kara 2013-06-08 11:26:14 -04:00 committed by Theodore Ts'o
parent bd78b1dae9
commit 70f4632b62
21 changed files with 145 additions and 101 deletions

View File

@ -1911,9 +1911,9 @@ static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
if (dirent->inode == 0) if (dirent->inode == 0)
return 0; return 0;
if (((dirent->name_len&0xFF) == 1) && (dirent->name[0] == '.')) if ((ext2fs_dirent_name_len(dirent) == 1) && (dirent->name[0] == '.'))
return 0; return 0;
if (((dirent->name_len&0xFF) == 2) && (dirent->name[0] == '.') && if ((ext2fs_dirent_name_len(dirent) == 2) && (dirent->name[0] == '.') &&
(dirent->name[1] == '.')) { (dirent->name[1] == '.')) {
rds->parent = dirent->inode; rds->parent = dirent->inode;
return 0; return 0;

View File

@ -308,7 +308,7 @@ static int rdump_dirent(struct ext2_dir_entry *dirent,
const char *dumproot = private; const char *dumproot = private;
struct ext2_inode inode; struct ext2_inode inode;
thislen = dirent->name_len & 0xFF; thislen = ext2fs_dirent_name_len(dirent);
strncpy(name, dirent->name, thislen); strncpy(name, dirent->name, thislen);
name[thislen] = 0; name[thislen] = 0;

View File

@ -183,7 +183,7 @@ static int filefrag_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
if (entry == DIRENT_DELETED_FILE) if (entry == DIRENT_DELETED_FILE)
return 0; return 0;
thislen = dirent->name_len & 0xFF; thislen = ext2fs_dirent_name_len(dirent);
strncpy(name, dirent->name, thislen); strncpy(name, dirent->name, thislen);
name[thislen] = '\0'; name[thislen] = '\0';
ino = dirent->inode; ino = dirent->inode;

View File

@ -79,15 +79,15 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
(unsigned long) blk); (unsigned long) blk);
return; return;
} }
thislen = ext2fs_dirent_name_len(dirent);
if (((offset + rec_len) > fs->blocksize) || if (((offset + rec_len) > fs->blocksize) ||
(rec_len < 8) || (rec_len < 8) ||
((rec_len % 4) != 0) || ((rec_len % 4) != 0) ||
((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) { (thislen + 8 > rec_len)) {
fprintf(pager, "Corrupted directory block (%llu)!\n", fprintf(pager, "Corrupted directory block (%llu)!\n",
blk); blk);
break; break;
} }
thislen = dirent->name_len & 0xFF;
strncpy(name, dirent->name, thislen); strncpy(name, dirent->name, thislen);
name[thislen] = '\0'; name[thislen] = '\0';
errcode = ext2fs_dirhash(hash_alg, name, errcode = ext2fs_dirhash(hash_alg, name,
@ -428,7 +428,7 @@ static int search_dir_block(ext2_filsys fs, blk64_t *blocknr,
return BLOCK_ABORT; return BLOCK_ABORT;
} }
if (dirent->inode && if (dirent->inode &&
p->len == (dirent->name_len & 0xFF) && p->len == ext2fs_dirent_name_len(dirent) &&
strncmp(p->search_name, dirent->name, strncmp(p->search_name, dirent->name,
p->len) == 0) { p->len) == 0) {
printf("Entry found at logical block %lld, " printf("Entry found at logical block %lld, "

View File

@ -61,7 +61,7 @@ static int list_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
struct list_dir_struct *ls = (struct list_dir_struct *) private; struct list_dir_struct *ls = (struct list_dir_struct *) private;
struct ext2_dir_entry_tail *t = (struct ext2_dir_entry_tail *) dirent; struct ext2_dir_entry_tail *t = (struct ext2_dir_entry_tail *) dirent;
thislen = dirent->name_len & 0xFF; thislen = ext2fs_dirent_name_len(dirent);
strncpy(name, dirent->name, thislen); strncpy(name, dirent->name, thislen);
name[thislen] = '\0'; name[thislen] = '\0';
ino = dirent->inode; ino = dirent->inode;
@ -105,7 +105,8 @@ static int list_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
t->det_checksum); t->det_checksum);
return 0; return 0;
} }
fprintf(ls->f, "(%d) %5d %5d ", dirent->name_len >> 8, fprintf(ls->f, "(%d) %5d %5d ",
ext2fs_dirent_file_type(dirent),
inode_uid(inode), inode_gid(inode)); inode_uid(inode), inode_gid(inode));
if (LINUX_S_ISDIR(inode.i_mode)) if (LINUX_S_ISDIR(inode.i_mode))
fprintf(ls->f, "%5d", inode.i_size); fprintf(ls->f, "%5d", inode.i_size);

View File

@ -45,7 +45,7 @@ static int ncheck_proc(struct ext2_dir_entry *dirent,
struct inode_walk_struct *iw = (struct inode_walk_struct *) private; struct inode_walk_struct *iw = (struct inode_walk_struct *) private;
struct ext2_inode inode; struct ext2_inode inode;
errcode_t retval; errcode_t retval;
int filetype = dirent->name_len >> 8; int filetype = ext2fs_dirent_file_type(dirent);
int i; int i;
iw->position++; iw->position++;
@ -66,11 +66,13 @@ static int ncheck_proc(struct ext2_dir_entry *dirent,
if (iw->parent) if (iw->parent)
printf("%u\t%s/%.*s", iw->iarray[i], printf("%u\t%s/%.*s", iw->iarray[i],
iw->parent, iw->parent,
(dirent->name_len & 0xFF), dirent->name); ext2fs_dirent_name_len(dirent),
dirent->name);
else else
printf("%u\t<%u>/%.*s", iw->iarray[i], printf("%u\t<%u>/%.*s", iw->iarray[i],
iw->dir, iw->dir,
(dirent->name_len & 0xFF), dirent->name); ext2fs_dirent_name_len(dirent),
dirent->name);
if (iw->check_dirent && filetype) { if (iw->check_dirent && filetype) {
if (!debugfs_read_inode(dirent->inode, &inode, if (!debugfs_read_inode(dirent->inode, &inode,
"ncheck") && "ncheck") &&

View File

@ -373,7 +373,7 @@ static _INLINE_ void expand_dirent_expression(FILE *f, ext2_filsys fs, char ch,
fprintf(f, "%u", dirent->inode); fprintf(f, "%u", dirent->inode);
break; break;
case 'n': case 'n':
len = dirent->name_len & 0xFF; len = ext2fs_dirent_name_len(dirent);
if ((ext2fs_get_rec_len(fs, dirent, &rec_len) == 0) && if ((ext2fs_get_rec_len(fs, dirent, &rec_len) == 0) &&
(len > rec_len)) (len > rec_len))
len = rec_len; len = rec_len;
@ -384,10 +384,10 @@ static _INLINE_ void expand_dirent_expression(FILE *f, ext2_filsys fs, char ch,
fprintf(f, "%u", rec_len); fprintf(f, "%u", rec_len);
break; break;
case 'l': case 'l':
fprintf(f, "%u", dirent->name_len & 0xFF); fprintf(f, "%u", ext2fs_dirent_name_len(dirent));
break; break;
case 't': case 't':
fprintf(f, "%u", dirent->name_len >> 8); fprintf(f, "%u", ext2fs_dirent_file_type(dirent));
break; break;
default: default:
no_dirent: no_dirent:

View File

@ -482,7 +482,7 @@ static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx,
retval = ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); retval = ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
if (retval) if (retval)
return; return;
if (((dirent->name_len & 0xFF) != 1) || if ((ext2fs_dirent_name_len(dirent) != 1) ||
(dirent->name[0] != '.') || (dirent->name[0] != '.') ||
(dirent->inode != pctx->ino) || (dirent->inode != pctx->ino) ||
(rec_len < 12) || (rec_len < 12) ||
@ -494,7 +494,7 @@ static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx,
retval = ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); retval = ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
if (retval) if (retval)
return; return;
if (((dirent->name_len & 0xFF) != 2) || if ((ext2fs_dirent_name_len(dirent) != 2) ||
(dirent->name[0] != '.') || (dirent->name[0] != '.') ||
(dirent->name[1] != '.') || (dirent->name[1] != '.') ||
(rec_len < 12) || (rec_len < 12) ||

View File

@ -302,9 +302,9 @@ static int dict_de_cmp(const void *a, const void *b)
int a_len, b_len; int a_len, b_len;
de_a = (const struct ext2_dir_entry *) a; de_a = (const struct ext2_dir_entry *) a;
a_len = de_a->name_len & 0xFF; a_len = ext2fs_dirent_name_len(de_a);
de_b = (const struct ext2_dir_entry *) b; de_b = (const struct ext2_dir_entry *) b;
b_len = de_b->name_len & 0xFF; b_len = ext2fs_dirent_name_len(de_b);
if (a_len != b_len) if (a_len != b_len)
return (a_len - b_len); return (a_len - b_len);
@ -357,7 +357,7 @@ static int check_dot(e2fsck_t ctx,
if (!dirent->inode) if (!dirent->inode)
problem = PR_2_MISSING_DOT; problem = PR_2_MISSING_DOT;
else if (((dirent->name_len & 0xFF) != 1) || else if ((ext2fs_dirent_name_len(dirent) != 1) ||
(dirent->name[0] != '.')) (dirent->name[0] != '.'))
problem = PR_2_1ST_NOT_DOT; problem = PR_2_1ST_NOT_DOT;
else if (dirent->name[1] != '\0') else if (dirent->name[1] != '\0')
@ -369,7 +369,8 @@ static int check_dot(e2fsck_t ctx,
if (rec_len < 12) if (rec_len < 12)
rec_len = dirent->rec_len = 12; rec_len = dirent->rec_len = 12;
dirent->inode = ino; dirent->inode = ino;
dirent->name_len = 1; ext2fs_dirent_set_name_len(dirent, 1);
ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
dirent->name[0] = '.'; dirent->name[0] = '.';
dirent->name[1] = '\0'; dirent->name[1] = '\0';
status = 1; status = 1;
@ -393,7 +394,9 @@ static int check_dot(e2fsck_t ctx,
(void) ext2fs_set_rec_len(ctx->fs, new_len, (void) ext2fs_set_rec_len(ctx->fs, new_len,
nextdir); nextdir);
nextdir->inode = 0; nextdir->inode = 0;
nextdir->name_len = 0; ext2fs_dirent_set_name_len(nextdir, 0);
ext2fs_dirent_set_file_type(nextdir,
EXT2_FT_UNKNOWN);
status = 1; status = 1;
} }
} }
@ -415,7 +418,7 @@ static int check_dotdot(e2fsck_t ctx,
if (!dirent->inode) if (!dirent->inode)
problem = PR_2_MISSING_DOT_DOT; problem = PR_2_MISSING_DOT_DOT;
else if (((dirent->name_len & 0xFF) != 2) || else if ((ext2fs_dirent_name_len(dirent) != 2) ||
(dirent->name[0] != '.') || (dirent->name[0] != '.') ||
(dirent->name[1] != '.')) (dirent->name[1] != '.'))
problem = PR_2_2ND_NOT_DOT_DOT; problem = PR_2_2ND_NOT_DOT_DOT;
@ -433,7 +436,8 @@ static int check_dotdot(e2fsck_t ctx,
* inode. This will get fixed in pass 3. * inode. This will get fixed in pass 3.
*/ */
dirent->inode = EXT2_ROOT_INO; dirent->inode = EXT2_ROOT_INO;
dirent->name_len = 2; ext2fs_dirent_set_name_len(dirent, 2);
ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
dirent->name[0] = '.'; dirent->name[0] = '.';
dirent->name[1] = '.'; dirent->name[1] = '.';
dirent->name[2] = '\0'; dirent->name[2] = '\0';
@ -461,7 +465,7 @@ static int check_name(e2fsck_t ctx,
int fixup = -1; int fixup = -1;
int ret = 0; int ret = 0;
for ( i = 0; i < (dirent->name_len & 0xFF); i++) { for ( i = 0; i < ext2fs_dirent_name_len(dirent); i++) {
if (dirent->name[i] == '/' || dirent->name[i] == '\0') { if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
if (fixup < 0) { if (fixup < 0) {
fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
@ -483,7 +487,7 @@ static _INLINE_ int check_filetype(e2fsck_t ctx,
ext2_ino_t dir_ino EXT2FS_ATTR((unused)), ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
struct problem_context *pctx) struct problem_context *pctx)
{ {
int filetype = dirent->name_len >> 8; int filetype = ext2fs_dirent_file_type(dirent);
int should_be = EXT2_FT_UNKNOWN; int should_be = EXT2_FT_UNKNOWN;
struct ext2_inode inode; struct ext2_inode inode;
@ -492,7 +496,7 @@ static _INLINE_ int check_filetype(e2fsck_t ctx,
if (filetype == 0 || if (filetype == 0 ||
!fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx)) !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
return 0; return 0;
dirent->name_len = dirent->name_len & 0xFF; ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
return 1; return 1;
} }
@ -518,7 +522,7 @@ static _INLINE_ int check_filetype(e2fsck_t ctx,
pctx) == 0) pctx) == 0)
return 0; return 0;
dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8; ext2fs_dirent_set_file_type(dirent, should_be);
return 1; return 1;
} }
@ -666,7 +670,7 @@ static void salvage_directory(ext2_filsys fs,
char *cp = (char *) dirent; char *cp = (char *) dirent;
int left; int left;
unsigned int rec_len, prev_rec_len; unsigned int rec_len, prev_rec_len;
unsigned int name_len = dirent->name_len & 0xFF; unsigned int name_len = ext2fs_dirent_name_len(dirent);
(void) ext2fs_get_rec_len(fs, dirent, &rec_len); (void) ext2fs_get_rec_len(fs, dirent, &rec_len);
left = fs->blocksize - *offset - rec_len; left = fs->blocksize - *offset - rec_len;
@ -720,7 +724,8 @@ static void salvage_directory(ext2_filsys fs,
} else { } else {
rec_len = fs->blocksize - *offset; rec_len = fs->blocksize - *offset;
(void) ext2fs_set_rec_len(fs, rec_len, dirent); (void) ext2fs_set_rec_len(fs, rec_len, dirent);
dirent->name_len = 0; ext2fs_dirent_set_name_len(dirent, 0);
ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
dirent->inode = 0; dirent->inode = 0;
} }
} }
@ -868,7 +873,7 @@ static int check_dir_block(ext2_filsys fs,
dx_dir->depth = root->indirect_levels + 1; dx_dir->depth = root->indirect_levels + 1;
} else if ((dirent->inode == 0) && } else if ((dirent->inode == 0) &&
(rec_len == fs->blocksize) && (rec_len == fs->blocksize) &&
(dirent->name_len == 0) && (ext2fs_dirent_name_len(dirent) == 0) &&
(ext2fs_le16_to_cpu(limit->limit) == (ext2fs_le16_to_cpu(limit->limit) ==
((fs->blocksize - (8 + dx_csum_size)) / ((fs->blocksize - (8 + dx_csum_size)) /
sizeof(struct ext2_dx_entry)))) sizeof(struct ext2_dx_entry))))
@ -915,6 +920,7 @@ skip_checksum:
do { do {
int group; int group;
ext2_ino_t first_unused_inode; ext2_ino_t first_unused_inode;
unsigned int name_len;
problem = 0; problem = 0;
dirent = (struct ext2_dir_entry *) (buf + offset); dirent = (struct ext2_dir_entry *) (buf + offset);
@ -924,7 +930,7 @@ skip_checksum:
if (((offset + rec_len) > fs->blocksize) || if (((offset + rec_len) > fs->blocksize) ||
(rec_len < 12) || (rec_len < 12) ||
((rec_len % 4) != 0) || ((rec_len % 4) != 0) ||
(((dirent->name_len & (unsigned) 0xFF)+8) > rec_len)) { ((ext2fs_dirent_name_len(dirent) + 8) > rec_len)) {
if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) { if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
salvage_directory(fs, dirent, prev, &offset); salvage_directory(fs, dirent, prev, &offset);
dir_modified++; dir_modified++;
@ -956,6 +962,7 @@ skip_checksum:
/* /*
* Make sure the inode listed is a legal one. * Make sure the inode listed is a legal one.
*/ */
name_len = ext2fs_dirent_name_len(dirent);
if (((dirent->inode != EXT2_ROOT_INO) && if (((dirent->inode != EXT2_ROOT_INO) &&
(dirent->inode < EXT2_FIRST_INODE(fs->super))) || (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
(dirent->inode > fs->super->s_inodes_count)) { (dirent->inode > fs->super->s_inodes_count)) {
@ -968,8 +975,7 @@ skip_checksum:
* clear it. * clear it.
*/ */
problem = PR_2_BB_INODE; problem = PR_2_BB_INODE;
} else if ((dot_state > 1) && } else if ((dot_state > 1) && (name_len == 1) &&
((dirent->name_len & 0xFF) == 1) &&
(dirent->name[0] == '.')) { (dirent->name[0] == '.')) {
/* /*
* If there's a '.' entry in anything other * If there's a '.' entry in anything other
@ -977,8 +983,7 @@ skip_checksum:
* duplicate entry that should be removed. * duplicate entry that should be removed.
*/ */
problem = PR_2_DUP_DOT; problem = PR_2_DUP_DOT;
} else if ((dot_state > 1) && } else if ((dot_state > 1) && (name_len == 2) &&
((dirent->name_len & 0xFF) == 2) &&
(dirent->name[0] == '.') && (dirent->name[0] == '.') &&
(dirent->name[1] == '.')) { (dirent->name[1] == '.')) {
/* /*
@ -996,8 +1001,7 @@ skip_checksum:
* directory hasn't been created yet. * directory hasn't been created yet.
*/ */
problem = PR_2_LINK_ROOT; problem = PR_2_LINK_ROOT;
} else if ((dot_state > 1) && } else if ((dot_state > 1) && (name_len == 0)) {
(dirent->name_len & 0xFF) == 0) {
/* /*
* Don't allow zero-length directory names. * Don't allow zero-length directory names.
*/ */
@ -1110,7 +1114,7 @@ skip_checksum:
#ifdef ENABLE_HTREE #ifdef ENABLE_HTREE
if (dx_db) { if (dx_db) {
ext2fs_dirhash(dx_dir->hashversion, dirent->name, ext2fs_dirhash(dx_dir->hashversion, dirent->name,
(dirent->name_len & 0xFF), ext2fs_dirent_name_len(dirent),
fs->super->s_hash_seed, &hash, 0); fs->super->s_hash_seed, &hash, 0);
if (hash < dx_db->min_hash) if (hash < dx_db->min_hash)
dx_db->min_hash = hash; dx_db->min_hash = hash;

View File

@ -612,7 +612,7 @@ static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
errcode_t retval; errcode_t retval;
struct problem_context pctx; struct problem_context pctx;
if ((dirent->name_len & 0xFF) != 2) if (ext2fs_dirent_name_len(dirent) != 2)
return 0; return 0;
if (strncmp(dirent->name, "..", 2)) if (strncmp(dirent->name, "..", 2))
return 0; return 0;
@ -632,10 +632,9 @@ static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
dirent->inode = fp->parent; dirent->inode = fp->parent;
if (fp->ctx->fs->super->s_feature_incompat & if (fp->ctx->fs->super->s_feature_incompat &
EXT2_FEATURE_INCOMPAT_FILETYPE) EXT2_FEATURE_INCOMPAT_FILETYPE)
dirent->name_len = (dirent->name_len & 0xFF) | ext2fs_dirent_set_file_type(dirent, EXT2_FT_DIR);
(EXT2_FT_DIR << 8);
else else
dirent->name_len = dirent->name_len & 0xFF; ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
fp->done++; fp->done++;
return DIRENT_ABORT | DIRENT_CHANGED; return DIRENT_ABORT | DIRENT_CHANGED;

View File

@ -109,7 +109,7 @@ static int fill_dir_block(ext2_filsys fs,
struct hash_entry *new_array, *ent; struct hash_entry *new_array, *ent;
struct ext2_dir_entry *dirent; struct ext2_dir_entry *dirent;
char *dir; char *dir;
unsigned int offset, dir_offset, rec_len; unsigned int offset, dir_offset, rec_len, name_len;
int hash_alg; int hash_alg;
if (blockcnt < 0) if (blockcnt < 0)
@ -142,20 +142,21 @@ static int fill_dir_block(ext2_filsys fs,
while (dir_offset < fs->blocksize) { while (dir_offset < fs->blocksize) {
dirent = (struct ext2_dir_entry *) (dir + dir_offset); dirent = (struct ext2_dir_entry *) (dir + dir_offset);
(void) ext2fs_get_rec_len(fs, dirent, &rec_len); (void) ext2fs_get_rec_len(fs, dirent, &rec_len);
name_len = ext2fs_dirent_name_len(dirent);
if (((dir_offset + rec_len) > fs->blocksize) || if (((dir_offset + rec_len) > fs->blocksize) ||
(rec_len < 8) || (rec_len < 8) ||
((rec_len % 4) != 0) || ((rec_len % 4) != 0) ||
(((dirent->name_len & 0xFF)+8U) > rec_len)) { (name_len + 8 > rec_len)) {
fd->err = EXT2_ET_DIR_CORRUPTED; fd->err = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT; return BLOCK_ABORT;
} }
dir_offset += rec_len; dir_offset += rec_len;
if (dirent->inode == 0) if (dirent->inode == 0)
continue; continue;
if (!fd->compress && ((dirent->name_len&0xFF) == 1) && if (!fd->compress && (name_len == 1) &&
(dirent->name[0] == '.')) (dirent->name[0] == '.'))
continue; continue;
if (!fd->compress && ((dirent->name_len&0xFF) == 2) && if (!fd->compress && (name_len == 2) &&
(dirent->name[0] == '.') && (dirent->name[1] == '.')) { (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
fd->parent = dirent->inode; fd->parent = dirent->inode;
continue; continue;
@ -172,13 +173,13 @@ static int fill_dir_block(ext2_filsys fs,
} }
ent = fd->harray + fd->num_array++; ent = fd->harray + fd->num_array++;
ent->dir = dirent; ent->dir = dirent;
fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); fd->dir_size += EXT2_DIR_REC_LEN(name_len);
ent->ino = dirent->inode; ent->ino = dirent->inode;
if (fd->compress) if (fd->compress)
ent->hash = ent->minor_hash = 0; ent->hash = ent->minor_hash = 0;
else { else {
fd->err = ext2fs_dirhash(hash_alg, dirent->name, fd->err = ext2fs_dirhash(hash_alg, dirent->name,
dirent->name_len & 0xFF, name_len,
fs->super->s_hash_seed, fs->super->s_hash_seed,
&ent->hash, &ent->minor_hash); &ent->hash, &ent->minor_hash);
if (fd->err) if (fd->err)
@ -203,18 +204,21 @@ static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
{ {
const struct hash_entry *he_a = (const struct hash_entry *) a; const struct hash_entry *he_a = (const struct hash_entry *) a;
const struct hash_entry *he_b = (const struct hash_entry *) b; const struct hash_entry *he_b = (const struct hash_entry *) b;
unsigned int he_a_len, he_b_len;
int ret; int ret;
int min_len; int min_len;
min_len = he_a->dir->name_len; he_a_len = ext2fs_dirent_name_len(he_a->dir);
if (min_len > he_b->dir->name_len) he_b_len = ext2fs_dirent_name_len(he_b->dir);
min_len = he_b->dir->name_len; min_len = he_a_len;
if (min_len > he_b_len)
min_len = he_b_len;
ret = strncmp(he_a->dir->name, he_b->dir->name, min_len); ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
if (ret == 0) { if (ret == 0) {
if (he_a->dir->name_len > he_b->dir->name_len) if (he_a_len > he_b_len)
ret = 1; ret = 1;
else if (he_a->dir->name_len < he_b->dir->name_len) else if (he_a_len < he_b_len)
ret = -1; ret = -1;
else else
ret = he_b->dir->inode - he_a->dir->inode; ret = he_b->dir->inode - he_a->dir->inode;
@ -297,10 +301,10 @@ static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
* expand the length of the filename beyond the padding available in * expand the length of the filename beyond the padding available in
* the directory entry. * the directory entry.
*/ */
static void mutate_name(char *str, __u16 *len) static void mutate_name(char *str, unsigned int *len)
{ {
int i; int i;
__u16 l = *len & 0xFF, h = *len & 0xff00; unsigned int l = *len;
/* /*
* First check to see if it looks the name has been mutated * First check to see if it looks the name has been mutated
@ -317,7 +321,7 @@ static void mutate_name(char *str, __u16 *len)
l = (l+3) & ~3; l = (l+3) & ~3;
str[l-2] = '~'; str[l-2] = '~';
str[l-1] = '0'; str[l-1] = '0';
*len = l | h; *len = l;
return; return;
} }
for (i = l-1; i >= 0; i--) { for (i = l-1; i >= 0; i--) {
@ -360,7 +364,7 @@ static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
int i, j; int i, j;
int fixed = 0; int fixed = 0;
char new_name[256]; char new_name[256];
__u16 new_len; unsigned int new_len;
int hash_alg; int hash_alg;
clear_problem_context(&pctx); clear_problem_context(&pctx);
@ -375,10 +379,10 @@ static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
ent = fd->harray + i; ent = fd->harray + i;
prev = ent - 1; prev = ent - 1;
if (!ent->dir->inode || if (!ent->dir->inode ||
((ent->dir->name_len & 0xFF) != (ext2fs_dirent_name_len(ent->dir) !=
(prev->dir->name_len & 0xFF)) || ext2fs_dirent_name_len(prev->dir)) ||
(strncmp(ent->dir->name, prev->dir->name, strncmp(ent->dir->name, prev->dir->name,
ent->dir->name_len & 0xFF))) ext2fs_dirent_name_len(ent->dir)))
continue; continue;
pctx.dirent = ent->dir; pctx.dirent = ent->dir;
if ((ent->dir->inode == prev->dir->inode) && if ((ent->dir->inode == prev->dir->inode) &&
@ -388,27 +392,25 @@ static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
fixed++; fixed++;
continue; continue;
} }
memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF); new_len = ext2fs_dirent_name_len(ent->dir);
new_len = ent->dir->name_len; memcpy(new_name, ent->dir->name, new_len);
mutate_name(new_name, &new_len); mutate_name(new_name, &new_len);
for (j=0; j < fd->num_array; j++) { for (j=0; j < fd->num_array; j++) {
if ((i==j) || if ((i==j) ||
((new_len & 0xFF) != (new_len !=
(fd->harray[j].dir->name_len & 0xFF)) || ext2fs_dirent_name_len(fd->harray[j].dir)) ||
(strncmp(new_name, fd->harray[j].dir->name, strncmp(new_name, fd->harray[j].dir->name, new_len))
new_len & 0xFF)))
continue; continue;
mutate_name(new_name, &new_len); mutate_name(new_name, &new_len);
j = -1; j = -1;
} }
new_name[new_len & 0xFF] = 0; new_name[new_len] = 0;
pctx.str = new_name; pctx.str = new_name;
if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) { if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
memcpy(ent->dir->name, new_name, new_len & 0xFF); memcpy(ent->dir->name, new_name, new_len);
ent->dir->name_len = new_len; ext2fs_dirent_set_name_len(ent->dir, new_len);
ext2fs_dirhash(hash_alg, ent->dir->name, ext2fs_dirhash(hash_alg, ent->dir->name, new_len,
ent->dir->name_len & 0xFF,
fs->super->s_hash_seed, fs->super->s_hash_seed,
&ent->hash, &ent->minor_hash); &ent->hash, &ent->minor_hash);
fixed++; fixed++;
@ -469,7 +471,7 @@ static errcode_t copy_dir_entries(e2fsck_t ctx,
ent = fd->harray + i; ent = fd->harray + i;
if (ent->dir->inode == 0) if (ent->dir->inode == 0)
continue; continue;
rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF); rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(ent->dir));
if (rec_len > left) { if (rec_len > left) {
if (left) { if (left) {
left += prev_rec_len; left += prev_rec_len;
@ -496,12 +498,16 @@ static errcode_t copy_dir_entries(e2fsck_t ctx,
outdir->hashes[outdir->num-1] = ent->hash; outdir->hashes[outdir->num-1] = ent->hash;
} }
dirent->inode = ent->dir->inode; dirent->inode = ent->dir->inode;
dirent->name_len = ent->dir->name_len; ext2fs_dirent_set_name_len(dirent,
ext2fs_dirent_name_len(ent->dir));
ext2fs_dirent_set_file_type(dirent,
ext2fs_dirent_file_type(ent->dir));
retval = ext2fs_set_rec_len(fs, rec_len, dirent); retval = ext2fs_set_rec_len(fs, rec_len, dirent);
if (retval) if (retval)
return retval; return retval;
prev_rec_len = rec_len; prev_rec_len = rec_len;
memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF); memcpy(dirent->name, ent->dir->name,
ext2fs_dirent_name_len(dirent));
offset += rec_len; offset += rec_len;
left -= rec_len; left -= rec_len;
if (left < slack) { if (left < slack) {
@ -535,19 +541,21 @@ static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
int csum_size = 0; int csum_size = 0;
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
filetype = EXT2_FT_DIR << 8; filetype = EXT2_FT_DIR;
memset(buf, 0, fs->blocksize); memset(buf, 0, fs->blocksize);
dir = (struct ext2_dir_entry *) buf; dir = (struct ext2_dir_entry *) buf;
dir->inode = ino; dir->inode = ino;
dir->name[0] = '.'; dir->name[0] = '.';
dir->name_len = 1 | filetype; ext2fs_dirent_set_name_len(dir, 1);
ext2fs_dirent_set_file_type(dir, filetype);
dir->rec_len = 12; dir->rec_len = 12;
dir = (struct ext2_dir_entry *) (buf + 12); dir = (struct ext2_dir_entry *) (buf + 12);
dir->inode = parent; dir->inode = parent;
dir->name[0] = '.'; dir->name[0] = '.';
dir->name[1] = '.'; dir->name[1] = '.';
dir->name_len = 2 | filetype; ext2fs_dirent_set_name_len(dir, 2);
ext2fs_dirent_set_file_type(dir, filetype);
dir->rec_len = fs->blocksize - 12; dir->rec_len = fs->blocksize - 12;
root = (struct ext2_dx_root_info *) (buf+24); root = (struct ext2_dx_root_info *) (buf+24);

View File

@ -83,7 +83,7 @@ static int ext2fs_validate_entry(ext2_filsys fs, char *buf,
offset += rec_len; offset += rec_len;
if ((rec_len < 8) || if ((rec_len < 8) ||
((rec_len % 4) != 0) || ((rec_len % 4) != 0) ||
((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) ((ext2fs_dirent_name_len(dirent)+8) > rec_len))
return 0; return 0;
} }
return (offset == final_offset); return (offset == final_offset);
@ -215,7 +215,7 @@ int ext2fs_process_dir_block(ext2_filsys fs,
if (((offset + rec_len) > fs->blocksize) || if (((offset + rec_len) > fs->blocksize) ||
(rec_len < 8) || (rec_len < 8) ||
((rec_len % 4) != 0) || ((rec_len % 4) != 0) ||
((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) { ((ext2fs_dirent_name_len(dirent)+8) > rec_len)) {
ctx->errcode = EXT2_ET_DIR_CORRUPTED; ctx->errcode = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT; return BLOCK_ABORT;
} }
@ -253,7 +253,7 @@ next:
next_real_entry += rec_len; next_real_entry += rec_len;
if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) { if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
size = ((dirent->name_len & 0xFF) + 11) & ~3; size = (ext2fs_dirent_name_len(dirent) + 11) & ~3;
if (rec_len != size) { if (rec_len != size) {
unsigned int final_offset; unsigned int final_offset;

View File

@ -803,6 +803,14 @@ struct ext2_dir_entry {
* stored in intel byte order, and the name_len field could never be * stored in intel byte order, and the name_len field could never be
* bigger than 255 chars, it's safe to reclaim the extra byte for the * bigger than 255 chars, it's safe to reclaim the extra byte for the
* file_type field. * file_type field.
*
* This structure is deprecated due to endianity issues. Please use struct
* ext2_dir_entry and accessor functions
* ext2fs_dirent_name_len
* ext2fs_dirent_set_name_len
* ext2fs_dirent_file_type
* ext2fs_dirent_set_file_type
* to get and set name_len and file_type fields.
*/ */
struct ext2_dir_entry_2 { struct ext2_dir_entry_2 {
__u32 inode; /* Inode number */ __u32 inode; /* Inode number */

View File

@ -1805,6 +1805,26 @@ _INLINE_ __u64 ext2fs_div64_ceil(__u64 a, __u64 b)
return ((a - 1) / b) + 1; return ((a - 1) / b) + 1;
} }
_INLINE_ int ext2fs_dirent_name_len(const struct ext2_dir_entry *entry)
{
return entry->name_len & 0xff;
}
_INLINE_ void ext2fs_dirent_set_name_len(struct ext2_dir_entry *entry, int len)
{
entry->name_len = (entry->name_len & 0xff00) | (len & 0xff);
}
_INLINE_ int ext2fs_dirent_file_type(const struct ext2_dir_entry *entry)
{
return entry->name_len >> 8;
}
_INLINE_ void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type)
{
entry->name_len = (entry->name_len & 0xff) | (type << 8);
}
#undef _INLINE_ #undef _INLINE_
#endif #endif

View File

@ -49,21 +49,20 @@ static int get_pathname_proc(struct ext2_dir_entry *dirent,
{ {
struct get_pathname_struct *gp; struct get_pathname_struct *gp;
errcode_t retval; errcode_t retval;
int name_len = ext2fs_dirent_name_len(dirent);
gp = (struct get_pathname_struct *) priv_data; gp = (struct get_pathname_struct *) priv_data;
if (((dirent->name_len & 0xFF) == 2) && if ((name_len == 2) && !strncmp(dirent->name, "..", 2))
!strncmp(dirent->name, "..", 2))
gp->parent = dirent->inode; gp->parent = dirent->inode;
if (dirent->inode == gp->search_ino) { if (dirent->inode == gp->search_ino) {
retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1, retval = ext2fs_get_mem(name_len + 1, &gp->name);
&gp->name);
if (retval) { if (retval) {
gp->errcode = retval; gp->errcode = retval;
return DIRENT_ABORT; return DIRENT_ABORT;
} }
strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF)); strncpy(gp->name, dirent->name, name_len);
gp->name[dirent->name_len & 0xFF] = '\0'; gp->name[name_len] = '\0';
return DIRENT_ABORT; return DIRENT_ABORT;
} }
return 0; return 0;

View File

@ -73,7 +73,7 @@ static int link_proc(struct ext2_dir_entry *dirent,
* truncate it and return. * truncate it and return.
*/ */
if (dirent->inode) { if (dirent->inode) {
min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); min_rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(dirent));
if (curr_rec_len < (min_rec_len + rec_len)) if (curr_rec_len < (min_rec_len + rec_len))
return ret; return ret;
rec_len = curr_rec_len - min_rec_len; rec_len = curr_rec_len - min_rec_len;
@ -83,7 +83,8 @@ static int link_proc(struct ext2_dir_entry *dirent,
next = (struct ext2_dir_entry *) (buf + offset + next = (struct ext2_dir_entry *) (buf + offset +
dirent->rec_len); dirent->rec_len);
next->inode = 0; next->inode = 0;
next->name_len = 0; ext2fs_dirent_set_name_len(next, 0);
ext2fs_dirent_set_file_type(next, 0);
ls->err = ext2fs_set_rec_len(ls->fs, rec_len, next); ls->err = ext2fs_set_rec_len(ls->fs, rec_len, next);
if (ls->err) if (ls->err)
return DIRENT_ABORT; return DIRENT_ABORT;
@ -97,10 +98,10 @@ static int link_proc(struct ext2_dir_entry *dirent,
if (curr_rec_len < rec_len) if (curr_rec_len < rec_len)
return ret; return ret;
dirent->inode = ls->inode; dirent->inode = ls->inode;
dirent->name_len = ls->namelen; ext2fs_dirent_set_name_len(dirent, ls->namelen);
strncpy(dirent->name, ls->name, ls->namelen); strncpy(dirent->name, ls->name, ls->namelen);
if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
dirent->name_len |= (ls->flags & 0x7) << 8; ext2fs_dirent_set_file_type(dirent, ls->flags & 0x7);
ls->done++; ls->done++;
return DIRENT_ABORT|DIRENT_CHANGED; return DIRENT_ABORT|DIRENT_CHANGED;

View File

@ -37,9 +37,9 @@ static int lookup_proc(struct ext2_dir_entry *dirent,
{ {
struct lookup_struct *ls = (struct lookup_struct *) priv_data; struct lookup_struct *ls = (struct lookup_struct *) priv_data;
if (ls->len != (dirent->name_len & 0xFF)) if (ls->len != ext2fs_dirent_name_len(dirent))
return 0; return 0;
if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF))) if (strncmp(ls->name, dirent->name, ext2fs_dirent_name_len(dirent)))
return 0; return 0;
*ls->inode = dirent->inode; *ls->inode = dirent->inode;
ls->found++; ls->found++;

View File

@ -56,12 +56,13 @@ errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
if (dir_ino) { if (dir_ino) {
if (fs->super->s_feature_incompat & if (fs->super->s_feature_incompat &
EXT2_FEATURE_INCOMPAT_FILETYPE) EXT2_FEATURE_INCOMPAT_FILETYPE)
filetype = EXT2_FT_DIR << 8; filetype = EXT2_FT_DIR;
/* /*
* Set up entry for '.' * Set up entry for '.'
*/ */
dir->inode = dir_ino; dir->inode = dir_ino;
dir->name_len = 1 | filetype; ext2fs_dirent_set_name_len(dir, 1);
ext2fs_dirent_set_file_type(dir, filetype);
dir->name[0] = '.'; dir->name[0] = '.';
rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1); rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1);
dir->rec_len = EXT2_DIR_REC_LEN(1); dir->rec_len = EXT2_DIR_REC_LEN(1);
@ -74,7 +75,8 @@ errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
if (retval) if (retval)
return retval; return retval;
dir->inode = parent_ino; dir->inode = parent_ino;
dir->name_len = 2 | filetype; ext2fs_dirent_set_name_len(dir, 2);
ext2fs_dirent_set_file_type(dir, filetype);
dir->name[0] = '.'; dir->name[0] = '.';
dir->name[1] = '.'; dir->name[1] = '.';

View File

@ -44,9 +44,9 @@ static int unlink_proc(struct ext2_dir_entry *dirent,
ls->prev = dirent; ls->prev = dirent;
if (ls->name) { if (ls->name) {
if ((dirent->name_len & 0xFF) != ls->namelen) if (ext2fs_dirent_name_len(dirent) != ls->namelen)
return 0; return 0;
if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF)) if (strncmp(ls->name, dirent->name, ext2fs_dirent_name_len(dirent)))
return 0; return 0;
} }
if (ls->inode) { if (ls->inode) {

View File

@ -515,7 +515,7 @@ static int rewrite_dir_block(ext2_filsys fs,
ctx->errcode = ext2fs_get_rec_len(fs, last_de, &rec_len); ctx->errcode = ext2fs_get_rec_len(fs, last_de, &rec_len);
if (ctx->errcode) if (ctx->errcode)
return BLOCK_ABORT; return BLOCK_ABORT;
name_size = last_de->name_len & 0xFF; name_size = ext2fs_dirent_name_len(last_de);
if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {

View File

@ -1591,7 +1591,7 @@ static int check_and_change_inodes(ext2_ino_t dir,
#ifdef RESIZE2FS_DEBUG #ifdef RESIZE2FS_DEBUG
if (is->rfs->flags & RESIZE_DEBUG_INODEMAP) if (is->rfs->flags & RESIZE_DEBUG_INODEMAP)
printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n", printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
dir, dirent->name_len&0xFF, dirent->name, dir, ext2fs_dirent_name_len(dirent), dirent->name,
dirent->inode, new_inode); dirent->inode, new_inode);
#endif #endif