/* * We don't define our `inode->i_op->truncate', and call it here, * because of: * - there is no way to know old size * - there is no way inform user about error, if it happens in `truncate' */ static int ufs_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; int error; error = inode_change_ok(inode, attr); if (error) return error; if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { error = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0; if (error) return error; } if (ia_valid & ATTR_SIZE && attr->ia_size != i_size_read(inode)) { loff_t old_i_size = inode->i_size; error = vmtruncate(inode, attr->ia_size); if (error) return error; error = ufs_truncate(inode, old_i_size); if (error) return error; } return inode_setattr(inode, attr); }
static int setattr_chown(struct inode *inode, struct iattr *attr) { struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *dibh; u32 ouid, ogid, nuid, ngid; int error; ouid = inode->i_uid; ogid = inode->i_gid; nuid = attr->ia_uid; ngid = attr->ia_gid; if (!(attr->ia_valid & ATTR_UID) || ouid == nuid) ouid = nuid = NO_QUOTA_CHANGE; if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) ogid = ngid = NO_QUOTA_CHANGE; if (!gfs2_alloc_get(ip)) return -ENOMEM; error = gfs2_quota_lock(ip, nuid, ngid); if (error) goto out_alloc; if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { error = gfs2_quota_check(ip, nuid, ngid); if (error) goto out_gunlock_q; } error = gfs2_trans_begin(sdp, RES_DINODE + 2 * RES_QUOTA, 0); if (error) goto out_gunlock_q; error = gfs2_meta_inode_buffer(ip, &dibh); if (error) goto out_end_trans; error = inode_setattr(inode, attr); gfs2_assert_warn(sdp, !error); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { u64 blocks = gfs2_get_inode_blocks(&ip->i_inode); gfs2_quota_change(ip, -blocks, ouid, ogid); gfs2_quota_change(ip, blocks, nuid, ngid); } out_end_trans: gfs2_trans_end(sdp); out_gunlock_q: gfs2_quota_unlock(ip); out_alloc: gfs2_alloc_put(ip); return error; }
/** Change attributes of an object referenced by dentry. */ int pvfs2_setattr(struct dentry *dentry, struct iattr *iattr) { int ret = -EINVAL; struct inode *inode = dentry->d_inode; gossip_debug(GOSSIP_INODE_DEBUG, "pvfs2_setattr: called on %s\n", dentry->d_name.name); ret = inode_change_ok(inode, iattr); if (ret == 0) { ret = inode_setattr(inode, iattr); gossip_debug(GOSSIP_INODE_DEBUG, "pvfs2_setattr: inode_setattr returned %d\n", ret); if (ret == 0) { ret = pvfs2_inode_setattr(inode, iattr); #if !defined(PVFS2_LINUX_KERNEL_2_4) && defined(HAVE_GENERIC_GETXATTR) && defined(CONFIG_FS_POSIX_ACL) if (!ret && (iattr->ia_valid & ATTR_MODE)) { /* change mod on a file that has ACLs */ ret = pvfs2_acl_chmod(inode); } #endif } } gossip_debug(GOSSIP_INODE_DEBUG, "pvfs2_setattr: returning %d\n", ret); return ret; }
int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) { struct inode *inode = dentry->d_inode; struct sysfs_dirent *sd = dentry->d_fsdata; int error; if (!sd) return -EINVAL; error = inode_change_ok(inode, iattr); if (error) return error; iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ error = inode_setattr(inode, iattr); if (error) return error; mutex_lock(&sysfs_mutex); error = sysfs_sd_setattr(sd, iattr); mutex_unlock(&sysfs_mutex); return error; }
int affs_notify_change(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; int error; pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid); error = inode_change_ok(inode,attr); if (error) goto out; if (((attr->ia_valid & ATTR_UID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETUID)) || ((attr->ia_valid & ATTR_GID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETGID)) || ((attr->ia_valid & ATTR_MODE) && (inode->i_sb->u.affs_sb.s_flags & (SF_SETMODE | SF_IMMUTABLE)))) { if (!(inode->i_sb->u.affs_sb.s_flags & SF_QUIET)) error = -EPERM; goto out; } if (attr->ia_valid & ATTR_MODE) inode->u.affs_i.i_protect = mode_to_prot(attr->ia_mode); inode_setattr(inode, attr); mark_inode_dirty(inode); error = 0; out: return error; }
int hpfs_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; int error = -EINVAL; lock_kernel(); if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root) goto out_unlock; if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) goto out_unlock; error = inode_change_ok(inode, attr); if (error) goto out_unlock; error = inode_setattr(inode, attr); if (error) goto out_unlock; hpfs_write_inode(inode); out_unlock: unlock_kernel(); return error; }
int affs_notify_change(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; int error; pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid); error = inode_change_ok(inode,attr); if (error) goto out; if (((attr->ia_valid & ATTR_UID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETUID)) || ((attr->ia_valid & ATTR_GID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETGID)) || ((attr->ia_valid & ATTR_MODE) && (AFFS_SB(inode->i_sb)->s_flags & (SF_SETMODE | SF_IMMUTABLE)))) { if (!(AFFS_SB(inode->i_sb)->s_flags & SF_QUIET)) error = -EPERM; goto out; } error = inode_setattr(inode, attr); if (!error && (attr->ia_valid & ATTR_MODE)) mode_to_prot(inode); out: return error; }
static int ospfs_notify_change(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; ospfs_inode_t *oi = ospfs_inode(inode->i_ino); int retval = 0; if (attr->ia_valid & ATTR_SIZE) { // We should not be able to change directory size if (oi->oi_ftype == OSPFS_FTYPE_DIR) return -EPERM; if ((retval = change_size(oi, attr->ia_size)) < 0) goto out; } if (attr->ia_valid & ATTR_MODE) // Set this inode's mode to the value 'attr->ia_mode'. oi->oi_mode = attr->ia_mode; if ((retval = inode_change_ok(inode, attr)) < 0 || (retval = inode_setattr(inode, attr)) < 0) goto out; out: return retval; }
static int replayfs_setattr(struct dentry *dentry, struct iattr *ia) { int error; struct inode *inode; replayfs_log_t log; replayfs_log_inode_t log_inode; inode = dentry->d_inode; error = replayfs_begin_log_operation(&log); if (error) { goto out; } replayfs_log_add_inode(&log, &log_inode, inode); error = inode_change_ok(inode, ia); if (!error) { error = inode_setattr(inode, ia); } replayfs_inode_modified_metadata(inode, &log, &log_inode); replayfs_log_inode_done(&log, &log_inode, inode->i_size); replayfs_end_log_operation(&log); out: return error; }
int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) { struct inode * inode = dentry->d_inode; struct sysfs_dirent * sd = dentry->d_fsdata; struct iattr * sd_iattr; unsigned int ia_valid = iattr->ia_valid; int error; if (!sd) return -EINVAL; sd_iattr = sd->s_iattr; error = inode_change_ok(inode, iattr); if (error) return error; error = inode_setattr(inode, iattr); if (error) return error; if (!sd_iattr) { /* setting attributes for the first time, allocate now */ sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL); if (!sd_iattr) return -ENOMEM; /* assign default attributes */ sd_iattr->ia_mode = sd->s_mode; sd_iattr->ia_uid = 0; sd_iattr->ia_gid = 0; sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME; sd->s_iattr = sd_iattr; } /* attributes were changed atleast once in past */ if (ia_valid & ATTR_UID) sd_iattr->ia_uid = iattr->ia_uid; if (ia_valid & ATTR_GID) sd_iattr->ia_gid = iattr->ia_gid; if (ia_valid & ATTR_ATIME) sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_MTIME) sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_CTIME) sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_MODE) { umode_t mode = iattr->ia_mode; if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) mode &= ~S_ISGID; sd_iattr->ia_mode = sd->s_mode = mode; } return error; }
/** * @brief Changes ownership of the dev * * @param name pointer to character * @param user uid_t type data * @param group gid_t type data * @return 0--success otherwise failure */ int mbtchar_chown(char *name, uid_t user, gid_t group) { struct path path; struct inode *inode = NULL; struct iattr newattrs; int ret = 0; int retrycount = 0; ENTER(); do { os_sched_timeout(30); ret = kern_path(name, LOOKUP_FOLLOW, &path); if (++retrycount >= 10) { PRINTM(ERROR, "mbtchar_chown(): fail to get kern_path\n"); LEAVE(); return -EFAULT; } } while (ret); inode = path.dentry->d_inode; mutex_lock(&inode->i_mutex); ret = mnt_want_write(path.mnt); if (ret) goto out_unlock; newattrs.ia_valid = ATTR_CTIME; if (user != (uid_t) (-1)) { newattrs.ia_valid |= ATTR_UID; newattrs.ia_uid = user; } if (group != (gid_t) (-1)) { newattrs.ia_valid |= ATTR_GID; newattrs.ia_gid = group; } if (!S_ISDIR(inode->i_mode)) newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; if (inode->i_op->setattr) ret = inode->i_op->setattr(path.dentry, &newattrs); else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ret = simple_setattr(path.dentry, &newattrs); #else ret = inode_setattr(inode, &newattrs); #endif mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); LEAVE(); return ret; out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); return ret; }
int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) { struct inode * inode = dentry->d_inode; struct sysfs_dirent * sd = dentry->d_fsdata; struct sysfs_inode_attrs *sd_attrs; struct iattr *iattrs; unsigned int ia_valid = iattr->ia_valid; int error; if (!sd) return -EINVAL; sd_attrs = sd->s_iattr; error = inode_change_ok(inode, iattr); if (error) return error; iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ error = inode_setattr(inode, iattr); if (error) return error; if (!sd_attrs) { /* setting attributes for the first time, allocate now */ sd_attrs = sysfs_init_inode_attrs(sd); if (!sd_attrs) return -ENOMEM; sd->s_iattr = sd_attrs; } /* attributes were changed at least once in past */ iattrs = &sd_attrs->ia_iattr; if (ia_valid & ATTR_UID) iattrs->ia_uid = iattr->ia_uid; if (ia_valid & ATTR_GID) iattrs->ia_gid = iattr->ia_gid; if (ia_valid & ATTR_ATIME) iattrs->ia_atime = timespec_trunc(iattr->ia_atime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_MTIME) iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_CTIME) iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_MODE) { umode_t mode = iattr->ia_mode; if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) mode &= ~S_ISGID; iattrs->ia_mode = sd->s_mode = mode; } return error; }
int fat_notify_change(struct dentry *dentry, struct iattr *attr) { struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); struct inode *inode = dentry->d_inode; int mask, error = 0; lock_kernel(); /* * Expand the file. Since inode_setattr() updates ->i_size * before calling the ->truncate(), but FAT needs to fill the * hole before it. */ if (attr->ia_valid & ATTR_SIZE) { if (attr->ia_size > inode->i_size) { error = fat_cont_expand(inode, attr->ia_size); //error = fat_cont_expand(inode, (unsigned int)attr->ia_size); if (error || attr->ia_valid == ATTR_SIZE) goto out; attr->ia_valid &= ~ATTR_SIZE; } } error = inode_change_ok(inode, attr); if (error) { if (sbi->options.quiet) error = 0; goto out; } if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != sbi->options.fs_uid)) || ((attr->ia_valid & ATTR_GID) && (attr->ia_gid != sbi->options.fs_gid)) || ((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~MSDOS_VALID_MODE))) error = -EPERM; if (error) { if (sbi->options.quiet) error = 0; goto out; } error = inode_setattr(inode, attr); if (error) goto out; if (S_ISDIR(inode->i_mode)) mask = sbi->options.fs_dmask; else mask = sbi->options.fs_fmask; inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask); out: unlock_kernel(); return error; }
/* * We do ->setattr() just to override size changes. Our size is the size * of the LVB and nothing else. */ static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr) { int error; struct inode *inode = dentry->d_inode; attr->ia_valid &= ~ATTR_SIZE; error = inode_change_ok(inode, attr); if (!error) error = inode_setattr(inode, attr); return error; }
static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; int error; if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) return -EPERM; error = inode_change_ok(inode, attr); if (!error) error = inode_setattr(inode, attr); return error; }
/** * @brief Changes permissions of the dev * * @param name pointer to character * @param mode mode_t type data * @return 0--success otherwise failure */ int mbtchar_chmod(char *name, mode_t mode) { struct path path; struct inode *inode; struct iattr newattrs; int ret; int retrycount = 0; ENTER(); do { os_sched_timeout(30); ret = kern_path(name, LOOKUP_FOLLOW, &path); if (++retrycount >= 10) { PRINTM(ERROR, "mbtchar_chmod(): fail to get kern_path\n"); LEAVE(); return -EFAULT; } } while (ret); inode = path.dentry->d_inode; mutex_lock(&inode->i_mutex); ret = mnt_want_write(path.mnt); if (ret) goto out_unlock; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; if (inode->i_op->setattr) ret = inode->i_op->setattr(path.dentry, &newattrs); else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ret = simple_setattr(path.dentry, &newattrs); #else ret = inode_setattr(inode, &newattrs); #endif mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); LEAVE(); return ret; out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); return ret; }
static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) { struct buffer_head *dibh; int error; error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { error = inode_setattr(&ip->i_inode, attr); gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } return error; }
//-------------------------------- iof_setattr --------------------------------- static int iof_setattr(struct dentry* dentry,struct iattr* attr) { struct inode* inode=dentry->d_inode; struct lxafs_inode_info* li=LXAFS_I(inode); int error=0; li->ia_valid|=attr->ia_valid; lock_kernel(); error=inode_change_ok(inode,attr); if(!error) error=inode_setattr(inode,attr); unlock_kernel(); if(!error) lxafs_write_inode(inode,1); return error; }
int hpfs_notify_change(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; int error=0; lock_kernel(); if ( ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) || (hpfs_sb(inode->i_sb)->sb_root == inode->i_ino) ) { error = -EINVAL; } else if ((error = inode_change_ok(inode, attr))) { } else if ((error = inode_setattr(inode, attr))) { } else { hpfs_write_inode(inode); } unlock_kernel(); return error; }
/** * proc_notify_change - Update inode's attributes and reflect to the dentry. * * @dentry: Pointer to "struct dentry". * @iattr: Pointer to "struct iattr". * * Returns 0 on success, negative value otherwise. * * The 2.4 kernels don't allow chmod()/chown() for files in /proc , * while the 2.6 kernels allow. * To permit management of /proc/ccs/ interface by non-root user, * I modified to allow chmod()/chown() of /proc/ccs/ interface like 2.6 kernels * by adding "struct inode_operations"->setattr hook. */ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) { struct inode *inode = dentry->d_inode; struct proc_dir_entry *de = PDE(inode); int error; error = inode_change_ok(inode, iattr); if (error) goto out; error = inode_setattr(inode, iattr); if (error) goto out; de->uid = inode->i_uid; de->gid = inode->i_gid; de->mode = inode->i_mode; out: return error; }
static int prlfs_inode_setattr(struct inode *inode, struct iattr *attr) { int ret = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ret = inode_setattr(inode, attr); #else if ((attr->ia_valid & ATTR_SIZE && attr->ia_size != i_size_read(inode))) { ret = inode_newsize_ok(inode, attr->ia_size); if (ret) goto out; truncate_setsize(inode, attr->ia_size); } setattr_copy(inode, attr); mark_inode_dirty(inode); out: #endif return ret; }
int jfs_setattr(struct dentry *dentry, struct iattr *iattr) { struct inode *inode = dentry->d_inode; int rc; rc = inode_change_ok(inode, iattr); if (rc) return rc; if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) || (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) { if (DQUOT_TRANSFER(inode, iattr)) return -EDQUOT; } rc = inode_setattr(inode, iattr); if (!rc && (iattr->ia_valid & ATTR_MODE)) rc = jfs_acl_chmod(inode); return rc; }
/* * We don't define our `inode->i_op->truncate', and call it here, * because of: * - there is no way to know old size * - there is no way inform user about error, if it happens in `truncate' */ static int ufs_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; int error; error = inode_change_ok(inode, attr); if (error) return error; if (ia_valid & ATTR_SIZE && attr->ia_size != i_size_read(inode)) { loff_t old_i_size = inode->i_size; error = vmtruncate(inode, attr->ia_size); if (error) return error; error = ufs_truncate(inode, old_i_size); if (error) return error; } return inode_setattr(inode, attr); }
int notify_change(register struct inode *inode, register struct iattr *attr) { int retval; attr->ia_ctime = CURRENT_TIME; if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME)) { if (!(attr->ia_valid & ATTR_ATIME_SET)) attr->ia_atime = attr->ia_ctime; if (!(attr->ia_valid & ATTR_MTIME_SET)) attr->ia_mtime = attr->ia_ctime; } #ifdef BLOAT_FS if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->notify_change) return inode->i_sb->s_op->notify_change(inode, attr); #endif if ((retval = inode_change_ok(inode, attr)) != 0) return retval; inode_setattr(inode, attr); return 0; }
static int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode ; int error ; if (attr->ia_valid & ATTR_SIZE) { /* version 2 items will be caught by the s_maxbytes check ** done for us in vmtruncate */ if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 && attr->ia_size > MAX_NON_LFS) return -EFBIG ; /* fill in hole pointers in the expanding truncate case. */ if (attr->ia_size > inode->i_size) { error = generic_cont_expand(inode, attr->ia_size) ; if (inode->u.reiserfs_i.i_prealloc_count > 0) { struct reiserfs_transaction_handle th ; /* we're changing at most 2 bitmaps, inode + super */ journal_begin(&th, inode->i_sb, 4) ; reiserfs_discard_prealloc (&th, inode); journal_end(&th, inode->i_sb, 4) ; } if (error) return error ; } } if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) || ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) && (get_inode_sd_version (inode) == STAT_DATA_V1)) /* stat data of format v3.5 has 16 bit uid and gid */ return -EINVAL; error = inode_change_ok(inode, attr) ; if (!error) inode_setattr(inode, attr) ; return error ; }
int notify_change(struct dentry * dentry, struct iattr * attr) { struct inode *inode = dentry->d_inode; int error; time_t now = CURRENT_TIME; unsigned int ia_valid = attr->ia_valid; attr->ia_ctime = now; if (!(ia_valid & ATTR_ATIME_SET)) attr->ia_atime = now; if (!(ia_valid & ATTR_MTIME_SET)) attr->ia_mtime = now; if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->notify_change) error = inode->i_sb->s_op->notify_change(dentry, attr); else { error = inode_change_ok(inode, attr); if (!error) inode_setattr(inode, attr); } return error; }
int notify_change(struct dentry * dentry, struct iattr * attr) { struct inode *inode = dentry->d_inode; int error; time_t now = CURRENT_TIME; unsigned int ia_valid = attr->ia_valid; if (!inode) BUG(); attr->ia_ctime = now; if (!(ia_valid & ATTR_ATIME_SET)) attr->ia_atime = now; if (!(ia_valid & ATTR_MTIME_SET)) attr->ia_mtime = now; lock_kernel(); if (inode->i_op && inode->i_op->setattr) error = inode->i_op->setattr(dentry, attr); else { error = inode_change_ok(inode, attr); if (!error) { if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; if (!error) error = inode_setattr(inode, attr); } } unlock_kernel(); if (!error) { unsigned long dn_mask = setattr_mask(ia_valid); if (dn_mask) dnotify_parent(dentry, dn_mask); } return error; }
int nilfs_setattr(struct dentry *dentry, struct iattr *iattr) { struct nilfs_transaction_info ti; struct inode *inode = dentry->d_inode; struct super_block *sb = inode->i_sb; int err; err = inode_change_ok(inode, iattr); if (err) return err; err = nilfs_transaction_begin(sb, &ti, 0); if (unlikely(err)) return err; err = inode_setattr(inode, iattr); if (!err && (iattr->ia_valid & ATTR_MODE)) err = nilfs_acl_chmod(inode); if (likely(!err)) err = nilfs_transaction_commit(sb); else nilfs_transaction_abort(sb); return err; }
int ncp_notify_change(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; int result = 0; __le32 info_mask; struct nw_modify_dos_info info; struct ncp_server *server; result = -EIO; lock_kernel(); server = NCP_SERVER(inode); if ((!server) || !ncp_conn_valid(server)) goto out; /* ageing the dentry to force validation */ ncp_age_dentry(server, dentry); result = inode_change_ok(inode, attr); if (result < 0) goto out; result = -EPERM; if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != server->m.uid))) goto out; if (((attr->ia_valid & ATTR_GID) && (attr->ia_gid != server->m.gid))) goto out; if (((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXUGO)))) goto out; info_mask = 0; memset(&info, 0, sizeof(info)); #if 1 if ((attr->ia_valid & ATTR_MODE) != 0) { umode_t newmode = attr->ia_mode; info_mask |= DM_ATTRIBUTES; if (S_ISDIR(inode->i_mode)) { newmode &= server->m.dir_mode; } else { #ifdef CONFIG_NCPFS_EXTRAS if (server->m.flags & NCP_MOUNT_EXTRAS) { /* any non-default execute bit set */ if (newmode & ~server->m.file_mode & S_IXUGO) info.attributes |= aSHARED | aSYSTEM; /* read for group/world and not in default file_mode */ else if (newmode & ~server->m.file_mode & S_IRUGO) info.attributes |= aSHARED; } else #endif newmode &= server->m.file_mode; } if (newmode & S_IWUGO) info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); else info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); #ifdef CONFIG_NCPFS_NFS_NS if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) { result = ncp_modify_nfs_info(server, NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum, attr->ia_mode, 0); if (result != 0) goto out; info.attributes &= ~(aSHARED | aSYSTEM); { /* mark partial success */ struct iattr tmpattr; tmpattr.ia_valid = ATTR_MODE; tmpattr.ia_mode = attr->ia_mode; result = inode_setattr(inode, &tmpattr); if (result) goto out; } } #endif } #endif /* Do SIZE before attributes, otherwise mtime together with size does not work... */ if ((attr->ia_valid & ATTR_SIZE) != 0) { int written; DPRINTK("ncpfs: trying to change size to %ld\n", attr->ia_size); if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { result = -EACCES; goto out; } ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, attr->ia_size, 0, "", &written); /* According to ndir, the changes only take effect after closing the file */ ncp_inode_close(inode); result = ncp_make_closed(inode); if (result) goto out; { struct iattr tmpattr; tmpattr.ia_valid = ATTR_SIZE; tmpattr.ia_size = attr->ia_size; result = inode_setattr(inode, &tmpattr); if (result) goto out; } } if ((attr->ia_valid & ATTR_CTIME) != 0) { info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE); ncp_date_unix2dos(attr->ia_ctime.tv_sec, &info.creationTime, &info.creationDate); } if ((attr->ia_valid & ATTR_MTIME) != 0) { info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); ncp_date_unix2dos(attr->ia_mtime.tv_sec, &info.modifyTime, &info.modifyDate); } if ((attr->ia_valid & ATTR_ATIME) != 0) { __le16 dummy; info_mask |= (DM_LAST_ACCESS_DATE); ncp_date_unix2dos(attr->ia_atime.tv_sec, &dummy, &info.lastAccessDate); } if (info_mask != 0) { result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), inode, info_mask, &info); if (result != 0) { result = -EACCES; if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { /* NetWare seems not to allow this. I do not know why. So, just tell the user everything went fine. This is a terrible hack, but I do not know how to do this correctly. */ result = 0; } else goto out; } #ifdef CONFIG_NCPFS_STRONG if ((!result) && (info_mask & DM_ATTRIBUTES)) NCP_FINFO(inode)->nwattr = info.attributes; #endif } if (!result) result = inode_setattr(inode, attr); out: unlock_kernel(); return result; }
int notify_change(struct dentry * dentry, struct iattr * attr) { struct inode *inode = dentry->d_inode; mode_t mode; int error; struct timespec now; unsigned int ia_valid = attr->ia_valid; mode = inode->i_mode; now = current_fs_time(inode->i_sb); attr->ia_ctime = now; if (!(ia_valid & ATTR_ATIME_SET)) attr->ia_atime = now; if (!(ia_valid & ATTR_MTIME_SET)) attr->ia_mtime = now; if (ia_valid & ATTR_KILL_SUID) { attr->ia_valid &= ~ATTR_KILL_SUID; if (mode & S_ISUID) { if (!(ia_valid & ATTR_MODE)) { ia_valid = attr->ia_valid |= ATTR_MODE; attr->ia_mode = inode->i_mode; } attr->ia_mode &= ~S_ISUID; } } if (ia_valid & ATTR_KILL_SGID) { attr->ia_valid &= ~ ATTR_KILL_SGID; if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { if (!(ia_valid & ATTR_MODE)) { ia_valid = attr->ia_valid |= ATTR_MODE; attr->ia_mode = inode->i_mode; } attr->ia_mode &= ~S_ISGID; } } if (!attr->ia_valid) return 0; if (ia_valid & ATTR_SIZE) down_write(&dentry->d_inode->i_alloc_sem); if (inode->i_op && inode->i_op->setattr) { error = security_inode_setattr(dentry, attr); if (!error) error = inode->i_op->setattr(dentry, attr); } else { error = inode_change_ok(inode, attr); if (!error) error = security_inode_setattr(dentry, attr); if (!error) { if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; if (!error) error = inode_setattr(inode, attr); } } if (ia_valid & ATTR_SIZE) up_write(&dentry->d_inode->i_alloc_sem); if (!error) fsnotify_change(dentry, ia_valid); return error; }