|
@@ -120,10 +120,11 @@ static void fuse_truncate(struct address_space *mapping, loff_t offset)
|
|
void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
|
|
void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
|
|
{
|
|
{
|
|
struct fuse_conn *fc = get_fuse_conn(inode);
|
|
struct fuse_conn *fc = get_fuse_conn(inode);
|
|
|
|
+ struct fuse_inode *fi = get_fuse_inode(inode);
|
|
loff_t oldsize;
|
|
loff_t oldsize;
|
|
|
|
|
|
inode->i_ino = attr->ino;
|
|
inode->i_ino = attr->ino;
|
|
- inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
|
|
|
|
|
|
+ inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
|
|
inode->i_nlink = attr->nlink;
|
|
inode->i_nlink = attr->nlink;
|
|
inode->i_uid = attr->uid;
|
|
inode->i_uid = attr->uid;
|
|
inode->i_gid = attr->gid;
|
|
inode->i_gid = attr->gid;
|
|
@@ -135,6 +136,15 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
|
|
inode->i_ctime.tv_sec = attr->ctime;
|
|
inode->i_ctime.tv_sec = attr->ctime;
|
|
inode->i_ctime.tv_nsec = attr->ctimensec;
|
|
inode->i_ctime.tv_nsec = attr->ctimensec;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Don't set the sticky bit in i_mode, unless we want the VFS
|
|
|
|
+ * to check permissions. This prevents failures due to the
|
|
|
|
+ * check in may_delete().
|
|
|
|
+ */
|
|
|
|
+ fi->orig_i_mode = inode->i_mode;
|
|
|
|
+ if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
|
|
|
|
+ inode->i_mode &= ~S_ISVTX;
|
|
|
|
+
|
|
spin_lock(&fc->lock);
|
|
spin_lock(&fc->lock);
|
|
oldsize = inode->i_size;
|
|
oldsize = inode->i_size;
|
|
i_size_write(inode, attr->size);
|
|
i_size_write(inode, attr->size);
|