0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/slab.h>
0011 #include "hpfs_fn.h"
0012
0013 static int hpfs_dir_release(struct inode *inode, struct file *filp)
0014 {
0015 hpfs_lock(inode->i_sb);
0016 hpfs_del_pos(inode, &filp->f_pos);
0017
0018 hpfs_unlock(inode->i_sb);
0019 return 0;
0020 }
0021
0022
0023
0024 static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
0025 {
0026 loff_t new_off = off + (whence == 1 ? filp->f_pos : 0);
0027 loff_t pos;
0028 struct quad_buffer_head qbh;
0029 struct inode *i = file_inode(filp);
0030 struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
0031 struct super_block *s = i->i_sb;
0032
0033
0034 if (whence == SEEK_DATA || whence == SEEK_HOLE)
0035 return -EINVAL;
0036
0037 inode_lock(i);
0038 hpfs_lock(s);
0039
0040
0041 if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
0042 pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;
0043 while (pos != new_off) {
0044 if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh);
0045 else goto fail;
0046 if (pos == 12) goto fail;
0047 }
0048 if (unlikely(hpfs_add_pos(i, &filp->f_pos) < 0)) {
0049 hpfs_unlock(s);
0050 inode_unlock(i);
0051 return -ENOMEM;
0052 }
0053 ok:
0054 filp->f_pos = new_off;
0055 hpfs_unlock(s);
0056 inode_unlock(i);
0057 return new_off;
0058 fail:
0059
0060 hpfs_unlock(s);
0061 inode_unlock(i);
0062 return -ESPIPE;
0063 }
0064
0065 static int hpfs_readdir(struct file *file, struct dir_context *ctx)
0066 {
0067 struct inode *inode = file_inode(file);
0068 struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
0069 struct quad_buffer_head qbh;
0070 struct hpfs_dirent *de;
0071 int lc;
0072 loff_t next_pos;
0073 unsigned char *tempname;
0074 int c1, c2 = 0;
0075 int ret = 0;
0076
0077 hpfs_lock(inode->i_sb);
0078
0079 if (hpfs_sb(inode->i_sb)->sb_chk) {
0080 if (hpfs_chk_sectors(inode->i_sb, inode->i_ino, 1, "dir_fnode")) {
0081 ret = -EFSERROR;
0082 goto out;
0083 }
0084 if (hpfs_chk_sectors(inode->i_sb, hpfs_inode->i_dno, 4, "dir_dnode")) {
0085 ret = -EFSERROR;
0086 goto out;
0087 }
0088 }
0089 if (hpfs_sb(inode->i_sb)->sb_chk >= 2) {
0090 struct buffer_head *bh;
0091 struct fnode *fno;
0092 int e = 0;
0093 if (!(fno = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
0094 ret = -EIOERROR;
0095 goto out;
0096 }
0097 if (!fnode_is_dir(fno)) {
0098 e = 1;
0099 hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
0100 (unsigned long)inode->i_ino);
0101 }
0102 if (hpfs_inode->i_dno != le32_to_cpu(fno->u.external[0].disk_secno)) {
0103 e = 1;
0104 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));
0105 }
0106 brelse(bh);
0107 if (e) {
0108 ret = -EFSERROR;
0109 goto out;
0110 }
0111 }
0112 lc = hpfs_sb(inode->i_sb)->sb_lowercase;
0113 if (ctx->pos == 12) {
0114 ctx->pos = 13;
0115 goto out;
0116 }
0117 if (ctx->pos == 13) {
0118 ret = -ENOENT;
0119 goto out;
0120 }
0121
0122 while (1) {
0123 again:
0124
0125
0126
0127 if (hpfs_sb(inode->i_sb)->sb_chk)
0128 if (hpfs_stop_cycles(inode->i_sb, ctx->pos, &c1, &c2, "hpfs_readdir")) {
0129 ret = -EFSERROR;
0130 goto out;
0131 }
0132 if (ctx->pos == 12)
0133 goto out;
0134 if (ctx->pos == 3 || ctx->pos == 4 || ctx->pos == 5) {
0135 pr_err("pos==%d\n", (int)ctx->pos);
0136 goto out;
0137 }
0138 if (ctx->pos == 0) {
0139 if (!dir_emit_dot(file, ctx))
0140 goto out;
0141 ctx->pos = 11;
0142 }
0143 if (ctx->pos == 11) {
0144 if (!dir_emit(ctx, "..", 2, hpfs_inode->i_parent_dir, DT_DIR))
0145 goto out;
0146 ctx->pos = 1;
0147 }
0148 if (ctx->pos == 1) {
0149 ret = hpfs_add_pos(inode, &file->f_pos);
0150 if (unlikely(ret < 0))
0151 goto out;
0152 ctx->pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1;
0153 }
0154 next_pos = ctx->pos;
0155 if (!(de = map_pos_dirent(inode, &next_pos, &qbh))) {
0156 ctx->pos = next_pos;
0157 ret = -EIOERROR;
0158 goto out;
0159 }
0160 if (de->first || de->last) {
0161 if (hpfs_sb(inode->i_sb)->sb_chk) {
0162 if (de->first && !de->last && (de->namelen != 2
0163 || de ->name[0] != 1 || de->name[1] != 1))
0164 hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", (unsigned long)ctx->pos);
0165 if (de->last && (de->namelen != 1 || de ->name[0] != 255))
0166 hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", (unsigned long)ctx->pos);
0167 }
0168 hpfs_brelse4(&qbh);
0169 ctx->pos = next_pos;
0170 goto again;
0171 }
0172 tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
0173 if (!dir_emit(ctx, tempname, de->namelen, le32_to_cpu(de->fnode), DT_UNKNOWN)) {
0174 if (tempname != de->name) kfree(tempname);
0175 hpfs_brelse4(&qbh);
0176 goto out;
0177 }
0178 ctx->pos = next_pos;
0179 if (tempname != de->name) kfree(tempname);
0180 hpfs_brelse4(&qbh);
0181 }
0182 out:
0183 hpfs_unlock(inode->i_sb);
0184 return ret;
0185 }
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
0203 {
0204 const unsigned char *name = dentry->d_name.name;
0205 unsigned len = dentry->d_name.len;
0206 struct quad_buffer_head qbh;
0207 struct hpfs_dirent *de;
0208 ino_t ino;
0209 int err;
0210 struct inode *result = NULL;
0211 struct hpfs_inode_info *hpfs_result;
0212
0213 hpfs_lock(dir->i_sb);
0214 if ((err = hpfs_chk_name(name, &len))) {
0215 if (err == -ENAMETOOLONG) {
0216 hpfs_unlock(dir->i_sb);
0217 return ERR_PTR(-ENAMETOOLONG);
0218 }
0219 goto end_add;
0220 }
0221
0222
0223
0224
0225
0226 de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, NULL, &qbh);
0227
0228
0229
0230
0231
0232 if (!de) goto end;
0233
0234
0235
0236
0237
0238 ino = le32_to_cpu(de->fnode);
0239
0240
0241
0242
0243
0244 result = iget_locked(dir->i_sb, ino);
0245 if (!result) {
0246 hpfs_error(dir->i_sb, "hpfs_lookup: can't get inode");
0247 result = ERR_PTR(-ENOMEM);
0248 goto bail1;
0249 }
0250 if (result->i_state & I_NEW) {
0251 hpfs_init_inode(result);
0252 if (de->directory)
0253 hpfs_read_inode(result);
0254 else if (le32_to_cpu(de->ea_size) && hpfs_sb(dir->i_sb)->sb_eas)
0255 hpfs_read_inode(result);
0256 else {
0257 result->i_mode |= S_IFREG;
0258 result->i_mode &= ~0111;
0259 result->i_op = &hpfs_file_iops;
0260 result->i_fop = &hpfs_file_ops;
0261 set_nlink(result, 1);
0262 }
0263 unlock_new_inode(result);
0264 }
0265 hpfs_result = hpfs_i(result);
0266 if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;
0267
0268 if (de->has_acl || de->has_xtd_perm) if (!sb_rdonly(dir->i_sb)) {
0269 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");
0270 iput(result);
0271 result = ERR_PTR(-EINVAL);
0272 goto bail1;
0273 }
0274
0275
0276
0277
0278
0279
0280 if (!result->i_ctime.tv_sec) {
0281 if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->creation_date))))
0282 result->i_ctime.tv_sec = 1;
0283 result->i_ctime.tv_nsec = 0;
0284 result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->write_date));
0285 result->i_mtime.tv_nsec = 0;
0286 result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->read_date));
0287 result->i_atime.tv_nsec = 0;
0288 hpfs_result->i_ea_size = le32_to_cpu(de->ea_size);
0289 if (!hpfs_result->i_ea_mode && de->read_only)
0290 result->i_mode &= ~0222;
0291 if (!de->directory) {
0292 if (result->i_size == -1) {
0293 result->i_size = le32_to_cpu(de->file_size);
0294 result->i_data.a_ops = &hpfs_aops;
0295 hpfs_i(result)->mmu_private = result->i_size;
0296
0297
0298
0299
0300
0301
0302 result->i_blocks = 1 + ((result->i_size + 511) >> 9);
0303 }
0304 }
0305 }
0306
0307 bail1:
0308 hpfs_brelse4(&qbh);
0309
0310
0311
0312
0313
0314 end:
0315 end_add:
0316 hpfs_unlock(dir->i_sb);
0317 return d_splice_alias(result, dentry);
0318 }
0319
0320 const struct file_operations hpfs_dir_ops =
0321 {
0322 .llseek = hpfs_dir_lseek,
0323 .read = generic_read_dir,
0324 .iterate_shared = hpfs_readdir,
0325 .release = hpfs_dir_release,
0326 .fsync = hpfs_file_fsync,
0327 .unlocked_ioctl = hpfs_ioctl,
0328 .compat_ioctl = compat_ptr_ioctl,
0329 };