return r;
}
-int Client::ll_create(vinodeno_t parent, const char *name, mode_t mode, int flags,
+int Client::ll_create(vinodeno_t parent, const char *name, mode_t mode, int flags,
struct stat *attr, Fh **fhp, int uid, int gid)
{
Mutex::Locker lock(client_lock);
tout(cct) << mode << std::endl;
tout(cct) << flags << std::endl;
+ bool created = false;
+ Inode *in = NULL;
Inode *dir = _ll_get_inode(parent);
- int r = _mknod(dir, name, mode, 0, uid, gid);
+ int r = _lookup(dir, name, &in);
+ if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL))
+ return -EEXIST;
+ if (r == -ENOENT && (flags & O_CREAT)) {
+ created = true;
+ r = _create(dir, name, flags, mode, &in, fhp,
+ 0, 0, 0,
+ NULL, uid, gid);
+ if (r < 0)
+ goto out;
+
+ in = (*fhp)->inode;
+ }
+
if (r < 0)
- return r;
- Dentry *dn = dir->dir->dentries[name];
- Inode *in = dn->inode;
+ goto out;
- r = _open(in, flags, mode, fhp, uid, gid);
- if (r >= 0) {
- Inode *in = (*fhp)->inode;
- fill_stat(in, attr);
- _ll_get(in);
- } else {
- attr->st_ino = 0;
+ assert(in);
+ fill_stat(in, attr);
+ _ll_get(in);
+
+ if (!created) {
+ uid_t uid = geteuid();
+ gid_t gid = getegid();
+ r = check_permissions(in, flags, uid, gid);
+ if (r < 0)
+ goto out;
+
+ r = _open(in, flags, mode, fhp);
+ if (r < 0)
+ goto out;
}
+
+out:
+ if (r < 0)
+ attr->st_ino = 0;
+
tout(cct) << (unsigned long)*fhp << std::endl;
tout(cct) << attr->st_ino << std::endl;
ldout(cct, 3) << "ll_create " << parent << " " << name << " 0" << oct << mode << dec << " " << flags
<< " = " << r << " (" << *fhp << " " << hex << attr->st_ino << dec << ")" << dendl;
- return 0;
+ return r;
}
int Client::ll_read(Fh *fh, loff_t off, loff_t len, bufferlist *bl)