staticint hpfs_readdir(struct file *file, struct dir_context *ctx)
{ struct inode *inode = file_inode(file); struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); struct quad_buffer_head qbh; struct hpfs_dirent *de; int lc;
loff_t next_pos; unsignedchar *tempname; int c1, c2 = 0; int ret = 0;
hpfs_lock(inode->i_sb);
if (hpfs_sb(inode->i_sb)->sb_chk) { if (hpfs_chk_sectors(inode->i_sb, inode->i_ino, 1, "dir_fnode")) {
ret = -EFSERROR; goto out;
} if (hpfs_chk_sectors(inode->i_sb, hpfs_inode->i_dno, 4, "dir_dnode")) {
ret = -EFSERROR; goto out;
}
} if (hpfs_sb(inode->i_sb)->sb_chk >= 2) { struct buffer_head *bh; struct fnode *fno; int e = 0; if (!(fno = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
ret = -EIOERROR; goto out;
} if (!fnode_is_dir(fno)) {
e = 1;
hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
(unsignedlong)inode->i_ino);
} if (hpfs_inode->i_dno != le32_to_cpu(fno->u.external[0].disk_secno)) {
e = 1;
hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, le32_to_cpu(fno->u.external[0].disk_secno));
}
brelse(bh); if (e) {
ret = -EFSERROR; goto out;
}
}
lc = hpfs_sb(inode->i_sb)->sb_lowercase; if (ctx->pos == 12) { /* diff -r requires this (note, that diff -r */
ctx->pos = 13; /* also fails on msdos filesystem in 2.0) */ goto out;
} if (ctx->pos == 13) {
ret = -ENOENT; goto out;
}
while (1) {
again: /* This won't work when cycle is longer than number of dirents accepted by filldir, but what can I do?
maybe killall -9 ls helps */ if (hpfs_sb(inode->i_sb)->sb_chk) if (hpfs_stop_cycles(inode->i_sb, ctx->pos, &c1, &c2, "hpfs_readdir")) {
ret = -EFSERROR; goto out;
} if (ctx->pos == 12) goto out; if (ctx->pos == 3 || ctx->pos == 4 || ctx->pos == 5) {
pr_err("pos==%d\n", (int)ctx->pos); goto out;
} if (ctx->pos == 0) { if (!dir_emit_dot(file, ctx)) goto out;
ctx->pos = 11;
} if (ctx->pos == 11) { if (!dir_emit(ctx, "..", 2, hpfs_inode->i_parent_dir, DT_DIR)) goto out;
ctx->pos = 1;
} if (ctx->pos == 1) {
ret = hpfs_add_pos(inode, &file->f_pos); if (unlikely(ret < 0)) goto out;
ctx->pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1;
}
next_pos = ctx->pos; if (!(de = map_pos_dirent(inode, &next_pos, &qbh))) {
ctx->pos = next_pos;
ret = -EIOERROR; goto out;
} if (de->first || de->last) { if (hpfs_sb(inode->i_sb)->sb_chk) { if (de->first && !de->last && (de->namelen != 2
|| de ->name[0] != 1 || de->name[1] != 1))
hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", (unsignedlong)ctx->pos); if (de->last && (de->namelen != 1 || de ->name[0] != 255))
hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", (unsignedlong)ctx->pos);
}
hpfs_brelse4(&qbh);
ctx->pos = next_pos; goto again;
}
tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3); if (!dir_emit(ctx, tempname, de->namelen, le32_to_cpu(de->fnode), DT_UNKNOWN)) { if (tempname != de->name) kfree(tempname);
hpfs_brelse4(&qbh); goto out;
}
ctx->pos = next_pos; if (tempname != de->name) kfree(tempname);
hpfs_brelse4(&qbh);
}
out:
hpfs_unlock(inode->i_sb); return ret;
}
/* * lookup. Search the specified directory for the specified name, set * *result to the corresponding inode. * * lookup uses the inode number to tell read_inode whether it is reading * the inode of a directory or a file -- file ino's are odd, directory * ino's are even. read_inode avoids i/o for file inodes; everything * needed is up here in the directory. (And file fnodes are out in * the boondocks.) * * - M.P.: this is over, sometimes we've got to read file's fnode for eas * inode numbers are just fnode sector numbers; iget lock is used * to tell read_inode to read fnode or not.
*/
hpfs_lock(dir->i_sb); if ((err = hpfs_chk_name(name, &len))) { if (err == -ENAMETOOLONG) {
hpfs_unlock(dir->i_sb); return ERR_PTR(-ENAMETOOLONG);
} goto end_add;
}
/* * '.' and '..' will never be passed here.
*/
de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, NULL, &qbh);
/* * This is not really a bailout, just means file not found.
*/
if (!de) goto end;
/* * Get inode number, what we're after.
*/
ino = le32_to_cpu(de->fnode);
/* * Go find or make an inode.
*/
result = iget_locked(dir->i_sb, ino); if (!result) {
hpfs_error(dir->i_sb, "hpfs_lookup: can't get inode");
result = ERR_PTR(-ENOMEM); goto bail1;
} if (result->i_state & I_NEW) {
hpfs_init_inode(result); if (de->directory)
hpfs_read_inode(result); elseif (le32_to_cpu(de->ea_size) && hpfs_sb(dir->i_sb)->sb_eas)
hpfs_read_inode(result); else {
result->i_mode |= S_IFREG;
result->i_mode &= ~0111;
result->i_op = &hpfs_file_iops;
result->i_fop = &hpfs_file_ops;
set_nlink(result, 1);
}
unlock_new_inode(result);
}
hpfs_result = hpfs_i(result); if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;
if (de->has_acl || de->has_xtd_perm) if (!sb_rdonly(dir->i_sb)) {
hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
iput(result);
result = ERR_PTR(-EINVAL); goto bail1;
}
/* * Fill in the info from the directory if this is a newly created * inode.
*/
if (!inode_get_ctime_sec(result)) {
time64_t csec = local_to_gmt(dir->i_sb, le32_to_cpu(de->creation_date));
inode_set_ctime(result, csec ? csec : 1, 0);
inode_set_mtime(result,
local_to_gmt(dir->i_sb, le32_to_cpu(de->write_date)),
0);
inode_set_atime(result,
local_to_gmt(dir->i_sb, le32_to_cpu(de->read_date)),
0);
hpfs_result->i_ea_size = le32_to_cpu(de->ea_size); if (!hpfs_result->i_ea_mode && de->read_only)
result->i_mode &= ~0222; if (!de->directory) { if (result->i_size == -1) {
result->i_size = le32_to_cpu(de->file_size);
result->i_data.a_ops = &hpfs_aops;
hpfs_i(result)->mmu_private = result->i_size; /* * i_blocks should count the fnode and any anodes. * We count 1 for the fnode and don't bother about * anodes -- the disk heads are on the directory band * and we want them to stay there.
*/
result->i_blocks = 1 + ((result->i_size + 511) >> 9);
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.