0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/namei.h>
0009 #include <linux/vbox_utils.h>
0010 #include "vfsmod.h"
0011
0012 static int vboxsf_dir_open(struct inode *inode, struct file *file)
0013 {
0014 struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
0015 struct shfl_createparms params = {};
0016 struct vboxsf_dir_info *sf_d;
0017 int err;
0018
0019 sf_d = vboxsf_dir_info_alloc();
0020 if (!sf_d)
0021 return -ENOMEM;
0022
0023 params.handle = SHFL_HANDLE_NIL;
0024 params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS |
0025 SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ;
0026
0027 err = vboxsf_create_at_dentry(file_dentry(file), ¶ms);
0028 if (err)
0029 goto err_free_dir_info;
0030
0031 if (params.result != SHFL_FILE_EXISTS) {
0032 err = -ENOENT;
0033 goto err_close;
0034 }
0035
0036 err = vboxsf_dir_read_all(sbi, sf_d, params.handle);
0037 if (err)
0038 goto err_close;
0039
0040 vboxsf_close(sbi->root, params.handle);
0041 file->private_data = sf_d;
0042 return 0;
0043
0044 err_close:
0045 vboxsf_close(sbi->root, params.handle);
0046 err_free_dir_info:
0047 vboxsf_dir_info_free(sf_d);
0048 return err;
0049 }
0050
0051 static int vboxsf_dir_release(struct inode *inode, struct file *file)
0052 {
0053 if (file->private_data)
0054 vboxsf_dir_info_free(file->private_data);
0055
0056 return 0;
0057 }
0058
0059 static unsigned int vboxsf_get_d_type(u32 mode)
0060 {
0061 unsigned int d_type;
0062
0063 switch (mode & SHFL_TYPE_MASK) {
0064 case SHFL_TYPE_FIFO:
0065 d_type = DT_FIFO;
0066 break;
0067 case SHFL_TYPE_DEV_CHAR:
0068 d_type = DT_CHR;
0069 break;
0070 case SHFL_TYPE_DIRECTORY:
0071 d_type = DT_DIR;
0072 break;
0073 case SHFL_TYPE_DEV_BLOCK:
0074 d_type = DT_BLK;
0075 break;
0076 case SHFL_TYPE_FILE:
0077 d_type = DT_REG;
0078 break;
0079 case SHFL_TYPE_SYMLINK:
0080 d_type = DT_LNK;
0081 break;
0082 case SHFL_TYPE_SOCKET:
0083 d_type = DT_SOCK;
0084 break;
0085 case SHFL_TYPE_WHITEOUT:
0086 d_type = DT_WHT;
0087 break;
0088 default:
0089 d_type = DT_UNKNOWN;
0090 break;
0091 }
0092 return d_type;
0093 }
0094
0095 static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx)
0096 {
0097 struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb);
0098 struct vboxsf_dir_info *sf_d = dir->private_data;
0099 struct shfl_dirinfo *info;
0100 struct vboxsf_dir_buf *b;
0101 unsigned int d_type;
0102 loff_t i, cur = 0;
0103 ino_t fake_ino;
0104 void *end;
0105 int err;
0106
0107 list_for_each_entry(b, &sf_d->info_list, head) {
0108 try_next_entry:
0109 if (ctx->pos >= cur + b->entries) {
0110 cur += b->entries;
0111 continue;
0112 }
0113
0114
0115
0116
0117
0118
0119
0120
0121 for (i = 0, info = b->buf; i < ctx->pos - cur; i++) {
0122 end = &info->name.string.utf8[info->name.size];
0123
0124 if (WARN_ON(end > (b->buf + b->used)))
0125 return false;
0126 info = end;
0127 }
0128
0129 end = &info->name.string.utf8[info->name.size];
0130 if (WARN_ON(end > (b->buf + b->used)))
0131 return false;
0132
0133
0134 d_type = vboxsf_get_d_type(info->info.attr.mode);
0135
0136
0137
0138
0139
0140 if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) {
0141 vbg_err("vboxsf: fake ino overflow, truncating dir\n");
0142 return false;
0143 }
0144 fake_ino = ctx->pos + 1;
0145
0146 if (sbi->nls) {
0147 char d_name[NAME_MAX];
0148
0149 err = vboxsf_nlscpy(sbi, d_name, NAME_MAX,
0150 info->name.string.utf8,
0151 info->name.length);
0152 if (err) {
0153
0154 ctx->pos += 1;
0155 goto try_next_entry;
0156 }
0157
0158 return dir_emit(ctx, d_name, strlen(d_name),
0159 fake_ino, d_type);
0160 }
0161
0162 return dir_emit(ctx, info->name.string.utf8, info->name.length,
0163 fake_ino, d_type);
0164 }
0165
0166 return false;
0167 }
0168
0169 static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx)
0170 {
0171 bool emitted;
0172
0173 do {
0174 emitted = vboxsf_dir_emit(dir, ctx);
0175 if (emitted)
0176 ctx->pos += 1;
0177 } while (emitted);
0178
0179 return 0;
0180 }
0181
0182 const struct file_operations vboxsf_dir_fops = {
0183 .open = vboxsf_dir_open,
0184 .iterate = vboxsf_dir_iterate,
0185 .release = vboxsf_dir_release,
0186 .read = generic_read_dir,
0187 .llseek = generic_file_llseek,
0188 };
0189
0190
0191
0192
0193
0194 static int vboxsf_dentry_revalidate(struct dentry *dentry, unsigned int flags)
0195 {
0196 if (flags & LOOKUP_RCU)
0197 return -ECHILD;
0198
0199 if (d_really_is_positive(dentry))
0200 return vboxsf_inode_revalidate(dentry) == 0;
0201 else
0202 return vboxsf_stat_dentry(dentry, NULL) == -ENOENT;
0203 }
0204
0205 const struct dentry_operations vboxsf_dentry_ops = {
0206 .d_revalidate = vboxsf_dentry_revalidate
0207 };
0208
0209
0210
0211 static struct dentry *vboxsf_dir_lookup(struct inode *parent,
0212 struct dentry *dentry,
0213 unsigned int flags)
0214 {
0215 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
0216 struct shfl_fsobjinfo fsinfo;
0217 struct inode *inode;
0218 int err;
0219
0220 dentry->d_time = jiffies;
0221
0222 err = vboxsf_stat_dentry(dentry, &fsinfo);
0223 if (err) {
0224 inode = (err == -ENOENT) ? NULL : ERR_PTR(err);
0225 } else {
0226 inode = vboxsf_new_inode(parent->i_sb);
0227 if (!IS_ERR(inode))
0228 vboxsf_init_inode(sbi, inode, &fsinfo, false);
0229 }
0230
0231 return d_splice_alias(inode, dentry);
0232 }
0233
0234 static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry,
0235 struct shfl_fsobjinfo *info)
0236 {
0237 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
0238 struct vboxsf_inode *sf_i;
0239 struct inode *inode;
0240
0241 inode = vboxsf_new_inode(parent->i_sb);
0242 if (IS_ERR(inode))
0243 return PTR_ERR(inode);
0244
0245 sf_i = VBOXSF_I(inode);
0246
0247 sf_i->force_restat = 1;
0248 vboxsf_init_inode(sbi, inode, info, false);
0249
0250 d_instantiate(dentry, inode);
0251
0252 return 0;
0253 }
0254
0255 static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry,
0256 umode_t mode, bool is_dir, bool excl, u64 *handle_ret)
0257 {
0258 struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
0259 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
0260 struct shfl_createparms params = {};
0261 int err;
0262
0263 params.handle = SHFL_HANDLE_NIL;
0264 params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW | SHFL_CF_ACCESS_READWRITE;
0265 if (is_dir)
0266 params.create_flags |= SHFL_CF_DIRECTORY;
0267 if (excl)
0268 params.create_flags |= SHFL_CF_ACT_FAIL_IF_EXISTS;
0269
0270 params.info.attr.mode = (mode & 0777) |
0271 (is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE);
0272 params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING;
0273
0274 err = vboxsf_create_at_dentry(dentry, ¶ms);
0275 if (err)
0276 return err;
0277
0278 if (params.result != SHFL_FILE_CREATED)
0279 return -EPERM;
0280
0281 err = vboxsf_dir_instantiate(parent, dentry, ¶ms.info);
0282 if (err)
0283 goto out;
0284
0285
0286 sf_parent_i->force_restat = 1;
0287
0288 out:
0289 if (err == 0 && handle_ret)
0290 *handle_ret = params.handle;
0291 else
0292 vboxsf_close(sbi->root, params.handle);
0293
0294 return err;
0295 }
0296
0297 static int vboxsf_dir_mkfile(struct user_namespace *mnt_userns,
0298 struct inode *parent, struct dentry *dentry,
0299 umode_t mode, bool excl)
0300 {
0301 return vboxsf_dir_create(parent, dentry, mode, false, excl, NULL);
0302 }
0303
0304 static int vboxsf_dir_mkdir(struct user_namespace *mnt_userns,
0305 struct inode *parent, struct dentry *dentry,
0306 umode_t mode)
0307 {
0308 return vboxsf_dir_create(parent, dentry, mode, true, true, NULL);
0309 }
0310
0311 static int vboxsf_dir_atomic_open(struct inode *parent, struct dentry *dentry,
0312 struct file *file, unsigned int flags, umode_t mode)
0313 {
0314 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
0315 struct vboxsf_handle *sf_handle;
0316 struct dentry *res = NULL;
0317 u64 handle;
0318 int err;
0319
0320 if (d_in_lookup(dentry)) {
0321 res = vboxsf_dir_lookup(parent, dentry, 0);
0322 if (IS_ERR(res))
0323 return PTR_ERR(res);
0324
0325 if (res)
0326 dentry = res;
0327 }
0328
0329
0330 if (!(flags & O_CREAT) || d_really_is_positive(dentry))
0331 return finish_no_open(file, res);
0332
0333 err = vboxsf_dir_create(parent, dentry, mode, false, flags & O_EXCL, &handle);
0334 if (err)
0335 goto out;
0336
0337 sf_handle = vboxsf_create_sf_handle(d_inode(dentry), handle, SHFL_CF_ACCESS_READWRITE);
0338 if (IS_ERR(sf_handle)) {
0339 vboxsf_close(sbi->root, handle);
0340 err = PTR_ERR(sf_handle);
0341 goto out;
0342 }
0343
0344 err = finish_open(file, dentry, generic_file_open);
0345 if (err) {
0346
0347 vboxsf_release_sf_handle(d_inode(dentry), sf_handle);
0348 goto out;
0349 }
0350
0351 file->private_data = sf_handle;
0352 file->f_mode |= FMODE_CREATED;
0353 out:
0354 dput(res);
0355 return err;
0356 }
0357
0358 static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry)
0359 {
0360 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
0361 struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
0362 struct inode *inode = d_inode(dentry);
0363 struct shfl_string *path;
0364 u32 flags;
0365 int err;
0366
0367 if (S_ISDIR(inode->i_mode))
0368 flags = SHFL_REMOVE_DIR;
0369 else
0370 flags = SHFL_REMOVE_FILE;
0371
0372 if (S_ISLNK(inode->i_mode))
0373 flags |= SHFL_REMOVE_SYMLINK;
0374
0375 path = vboxsf_path_from_dentry(sbi, dentry);
0376 if (IS_ERR(path))
0377 return PTR_ERR(path);
0378
0379 err = vboxsf_remove(sbi->root, path, flags);
0380 __putname(path);
0381 if (err)
0382 return err;
0383
0384
0385 sf_parent_i->force_restat = 1;
0386
0387 return 0;
0388 }
0389
0390 static int vboxsf_dir_rename(struct user_namespace *mnt_userns,
0391 struct inode *old_parent,
0392 struct dentry *old_dentry,
0393 struct inode *new_parent,
0394 struct dentry *new_dentry,
0395 unsigned int flags)
0396 {
0397 struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb);
0398 struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent);
0399 struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent);
0400 u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS;
0401 struct shfl_string *old_path, *new_path;
0402 int err;
0403
0404 if (flags)
0405 return -EINVAL;
0406
0407 old_path = vboxsf_path_from_dentry(sbi, old_dentry);
0408 if (IS_ERR(old_path))
0409 return PTR_ERR(old_path);
0410
0411 new_path = vboxsf_path_from_dentry(sbi, new_dentry);
0412 if (IS_ERR(new_path)) {
0413 err = PTR_ERR(new_path);
0414 goto err_put_old_path;
0415 }
0416
0417 if (d_inode(old_dentry)->i_mode & S_IFDIR)
0418 shfl_flags = 0;
0419
0420 err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags);
0421 if (err == 0) {
0422
0423 sf_new_parent_i->force_restat = 1;
0424 sf_old_parent_i->force_restat = 1;
0425 }
0426
0427 __putname(new_path);
0428 err_put_old_path:
0429 __putname(old_path);
0430 return err;
0431 }
0432
0433 static int vboxsf_dir_symlink(struct user_namespace *mnt_userns,
0434 struct inode *parent, struct dentry *dentry,
0435 const char *symname)
0436 {
0437 struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
0438 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
0439 int symname_size = strlen(symname) + 1;
0440 struct shfl_string *path, *ssymname;
0441 struct shfl_fsobjinfo info;
0442 int err;
0443
0444 path = vboxsf_path_from_dentry(sbi, dentry);
0445 if (IS_ERR(path))
0446 return PTR_ERR(path);
0447
0448 ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL);
0449 if (!ssymname) {
0450 __putname(path);
0451 return -ENOMEM;
0452 }
0453 ssymname->length = symname_size - 1;
0454 ssymname->size = symname_size;
0455 memcpy(ssymname->string.utf8, symname, symname_size);
0456
0457 err = vboxsf_symlink(sbi->root, path, ssymname, &info);
0458 kfree(ssymname);
0459 __putname(path);
0460 if (err) {
0461
0462 return (err == -EROFS) ? -EPERM : err;
0463 }
0464
0465 err = vboxsf_dir_instantiate(parent, dentry, &info);
0466 if (err)
0467 return err;
0468
0469
0470 sf_parent_i->force_restat = 1;
0471 return 0;
0472 }
0473
0474 const struct inode_operations vboxsf_dir_iops = {
0475 .lookup = vboxsf_dir_lookup,
0476 .create = vboxsf_dir_mkfile,
0477 .mkdir = vboxsf_dir_mkdir,
0478 .atomic_open = vboxsf_dir_atomic_open,
0479 .rmdir = vboxsf_dir_unlink,
0480 .unlink = vboxsf_dir_unlink,
0481 .rename = vboxsf_dir_rename,
0482 .symlink = vboxsf_dir_symlink,
0483 .getattr = vboxsf_getattr,
0484 .setattr = vboxsf_setattr,
0485 };