/* * Truncate a file. * The calling routines must make sure to update the ctime * field and call notify_change. * * XXX Nobody calls this thing? -DaveM * N.B. After this call fhp needs an fh_put */ int nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size) { struct dentry *dentry; struct inode *inode; struct iattr newattrs; int err; kernel_cap_t saved_cap; err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE | MAY_TRUNC); if (err) goto out; dentry = fhp->fh_dentry; inode = dentry->d_inode; err = get_write_access(inode); if (err) goto out_nfserr; /* Things look sane, lock and do it. */ fh_lock(fhp); DQUOT_INIT(inode); newattrs.ia_size = size; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; if (current->fsuid != 0) { saved_cap = current->cap_effective; cap_clear(current->cap_effective); } err = notify_change(dentry, &newattrs); if (current->fsuid != 0) current->cap_effective = saved_cap; if (!err) { vmtruncate(inode, size); if (inode->i_op && inode->i_op->truncate) inode->i_op->truncate(inode); } put_write_access(inode); DQUOT_DROP(inode); fh_unlock(fhp); out_nfserr: if (err) err = nfserrno(-err); out: return err; }
/* If times==NULL, set access and modification to current time, * must be owner or have write permission. * Else, update from *times, must be owner or super user. */ long do_utimes(int dfd, char __user *filename, struct timeval *times) { int error; struct nameidata nd; struct inode * inode; struct iattr newattrs; error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); if (error) goto out; inode = nd.dentry->d_inode; error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; /* Don't worry, the checks are done in inode_change_ok() */ newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; if (times) { error = -EPERM; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) goto dput_and_out; newattrs.ia_atime.tv_sec = times[0].tv_sec; newattrs.ia_atime.tv_nsec = times[0].tv_usec * 1000; newattrs.ia_mtime.tv_sec = times[1].tv_sec; newattrs.ia_mtime.tv_nsec = times[1].tv_usec * 1000; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; } else { error = -EACCES; if (IS_IMMUTABLE(inode)) goto dput_and_out; if (current->fsuid != inode->i_uid && (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } mutex_lock(&inode->i_mutex); error = notify_change(nd.dentry, &newattrs); mutex_unlock(&inode->i_mutex); dput_and_out: path_release(&nd); out: return error; }
int do_truncate(struct dentry *dentry, loff_t length) { int err; struct iattr newattrs; /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */ if (length < 0) return -EINVAL; newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; down(&dentry->d_inode->i_sem); err = notify_change(dentry, &newattrs); up(&dentry->d_inode->i_sem); return err; }
static int nfsio_truncate(struct ploop_io * io, struct file * file, __u32 alloc_head) { int err; struct iattr newattrs; if (file->f_mapping != io->files.mapping) return -EINVAL; newattrs.ia_size = (u64)alloc_head << (io->plo->cluster_log + 9); newattrs.ia_valid = ATTR_SIZE; mutex_lock(&io->files.inode->i_mutex); err = notify_change(F_DENTRY(file), &newattrs); mutex_unlock(&io->files.inode->i_mutex); return err; }
bool edit_graphics_rep::mouse_graphics (string type, SI x, SI y, int m, time_t t) { (void) t; // apply_changes (); // FIXME: remove after review of synchronization frame f= find_frame (); if (!is_nil (f)) { if (!over_graphics (x, y)) return false; if (type == "move" || type == "dragging") if (check_event (MOTION_EVENT)) return true; point p = f [point (x, y)]; graphical_select (p[0], p[1]); // init the caching for adjust(). p = adjust (p); gr_x= p[0]; gr_y= p[1]; string sx= as_string (p[0]); string sy= as_string (p[1]); invalidate_graphical_object (); call ("set-keyboard-modifiers", object (m)); if (type == "move") call ("graphics-move-point", sx, sy); else if (type == "release-left") call ("graphics-insert-point", sx, sy); else if (type == "release-middle") call ("graphics-remove-point", sx, sy); else if (type == "release-right") call ("graphics-last-point", sx, sy); else if (type == "start-drag") call ("graphics-start-drag", sx, sy); else if (type == "dragging") call ("graphics-dragging", sx, sy); else if (type == "end-drag") call ("graphics-end-drag", sx, sy); else if (type == "start-right-drag") call ("graphics-start-right-drag", sx, sy); else if (type == "right-dragging") call ("graphics-right-dragging", sx, sy); else if (type == "end-right-drag") call ("graphics-end-right-drag", sx, sy); invalidate_graphical_object (); notify_change (THE_CURSOR); return true; } return false; }
asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count) { int error; struct file * file; struct inode * inode; int written; if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode)) return -EBADF; if (!(file->f_mode & 2)) return -EBADF; if (!file->f_op || !file->f_op->write) return -EINVAL; if (!count) return 0; error = locks_verify_area(FLOCK_VERIFY_WRITE,inode,file,file->f_pos,count); if (error) return error; error = verify_area(VERIFY_READ,buf,count); if (error) return error; /* * If data has been written to the file, remove the setuid and * the setgid bits. We do it anyway otherwise there is an * extremely exploitable race - does your OS get it right |-> * * Set ATTR_FORCE so it will always be changed. */ if (!suser() && (inode->i_mode & (S_ISUID | S_ISGID))) { struct iattr newattrs; /* * Don't turn off setgid if no group execute. This special * case marks candidates for mandatory locking. */ newattrs.ia_mode = inode->i_mode & ~(S_ISUID | ((inode->i_mode & S_IXGRP) ? S_ISGID : 0)); newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_FORCE; notify_change(inode, &newattrs); } down(&inode->i_sem); written = file->f_op->write(inode,file,buf,count); up(&inode->i_sem); return written; }
static void call_notify_change(void *args) { struct notify_change_args *a = args; struct inode *h_inode; h_inode = a->path->dentry->d_inode; IMustLock(h_inode); *a->errp = -EPERM; if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { /* lockdep_off(); */ *a->errp = notify_change(a->path->dentry, a->ia); /* lockdep_on(); */ if (!*a->errp) vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/ } AuTraceErr(*a->errp); }
static int fixup_tty_attrs(struct cpt_inode_image *ii, struct file *master, struct cpt_context *ctx) { int err; struct iattr newattrs; struct dentry *d = master->f_dentry; newattrs.ia_valid = ATTR_UID|ATTR_GID|ATTR_MODE; newattrs.ia_uid = ii->cpt_uid; newattrs.ia_gid = ii->cpt_gid; newattrs.ia_mode = ii->cpt_mode; mutex_lock(&d->d_inode->i_mutex); err = notify_change(d, &newattrs); mutex_unlock(&d->d_inode->i_mutex); return err; }
/*! 2017. 8.12 study -ing */ static int handle_remove(const char *nodename, struct device *dev) { struct path parent; struct dentry *dentry; int deleted = 0; int err; dentry = kern_path_locked(nodename, &parent); if (IS_ERR(dentry)) return PTR_ERR(dentry); if (dentry->d_inode) { struct kstat stat; struct path p = {.mnt = parent.mnt, .dentry = dentry}; err = vfs_getattr(&p, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { struct iattr newattrs; /* * before unlinking this node, reset permissions * of possible references like hardlinks */ newattrs.ia_uid = GLOBAL_ROOT_UID; newattrs.ia_gid = GLOBAL_ROOT_GID; newattrs.ia_mode = stat.mode & ~0777; newattrs.ia_valid = ATTR_UID|ATTR_GID|ATTR_MODE; mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs, NULL); mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(parent.dentry->d_inode, dentry, NULL); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); mutex_unlock(&parent.dentry->d_inode->i_mutex); path_put(&parent); if (deleted && strchr(nodename, '/')) delete_path(nodename); return err; }
SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) { struct path path; struct inode *inode; int error; struct iattr newattrs; error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); if (error) goto out; inode = path.dentry->d_inode; error = mnt_want_write(path.mnt); if (error) goto dput_and_out; if (!gr_acl_handle_chmod(path.dentry, path.mnt, mode)) { error = -EACCES; goto out_drop_write; } mutex_lock(&inode->i_mutex); if (mode == (mode_t) -1) mode = inode->i_mode; if (gr_handle_chroot_chmod(path.dentry, path.mnt, mode)) { error = -EACCES; mutex_unlock(&inode->i_mutex); goto out_drop_write; } newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; error = notify_change(path.dentry, &newattrs); mutex_unlock(&inode->i_mutex); out_drop_write: mnt_drop_write(path.mnt); dput_and_out: path_put(&path); out: return error; }
/** * sysfs_chmod_file - update the modified mode value on an object attribute. * @kobj: object we're acting for. * @attr: attribute descriptor. * @mode: file permissions. * */ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { struct sysfs_dirent *victim_sd = NULL; struct dentry *victim = NULL; struct inode * inode; struct iattr newattrs; int rc; rc = -ENOENT; victim_sd = sysfs_get_dirent(kobj->sd, attr->name); if (!victim_sd) goto out; mutex_lock(&sysfs_rename_mutex); victim = sysfs_get_dentry(victim_sd); mutex_unlock(&sysfs_rename_mutex); if (IS_ERR(victim)) { rc = PTR_ERR(victim); victim = NULL; goto out; } inode = victim->d_inode; mutex_lock(&inode->i_mutex); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; rc = notify_change(victim, &newattrs); if (rc == 0) { mutex_lock(&sysfs_mutex); victim_sd->s_mode = newattrs.ia_mode; mutex_unlock(&sysfs_mutex); } mutex_unlock(&inode->i_mutex); out: dput(victim); sysfs_put(victim_sd); return rc; }
int ovl_setattr(struct dentry *dentry, struct iattr *attr) { int err; struct dentry *upperdentry; const struct cred *old_cred; /* * Check for permissions before trying to copy-up. This is redundant * since it will be rechecked later by ->setattr() on upper dentry. But * without this, copy-up can be triggered by just about anybody. * * We don't initialize inode->size, which just means that * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not * check for a swapfile (which this won't be anyway). */ err = setattr_prepare(dentry, attr); if (err) return err; err = ovl_want_write(dentry); if (err) goto out; err = ovl_copy_up(dentry); if (!err) { upperdentry = ovl_dentry_upper(dentry); if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) attr->ia_valid &= ~ATTR_MODE; inode_lock(upperdentry->d_inode); old_cred = ovl_override_creds(dentry->d_sb); err = notify_change(upperdentry, attr, NULL); revert_creds(old_cred); if (!err) ovl_copyattr(upperdentry->d_inode, dentry->d_inode); inode_unlock(upperdentry->d_inode); } ovl_drop_write(dentry); out: return err; }
SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) { struct inode * inode; struct dentry * dentry; struct file * file; int err = -EBADF; struct iattr newattrs; file = fget(fd); if (!file) goto out; //ASUS_BSP +++ Jimmy,Josh "remove fuse" if(strcmp(file->f_vfsmnt->mnt_mountpoint->d_iname,"sdcard")==0){ err = -ENOSYS; goto out_putf; } //ASUS_BSP --- Jimmy,Josh "remove fuse" dentry = file->f_path.dentry; inode = dentry->d_inode; audit_inode(NULL, dentry); err = mnt_want_write_file(file); if (err) goto out_putf; mutex_lock(&inode->i_mutex); err = security_path_chmod(dentry, file->f_vfsmnt, mode); if (err) goto out_unlock; if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(file->f_path.mnt); out_putf: fput(file); out: return err; }
int handle_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs) { int err; struct iattr newattrs; /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */ if(length < 0) return -EINVAL; newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | time_attrs; /* Remove suid/sgid on truncate too */ newattrs.ia_valid |= should_remove_suid(dentry); mutex_lock(&dentry->d_inode->i_mutex); err = notify_change(dentry, &newattrs); mutex_unlock(&dentry->d_inode->i_mutex); return err; }
static int chown_common(struct path *path, uid_t user, gid_t group) { struct inode *inode = path->dentry->d_inode; struct inode *delegated_inode = NULL; int error; struct iattr newattrs; kuid_t uid; kgid_t gid; uid = make_kuid(current_user_ns(), user); gid = make_kgid(current_user_ns(), group); retry_deleg: newattrs.ia_valid = ATTR_CTIME; if (user != (uid_t) -1) { if (!uid_valid(uid)) return -EINVAL; newattrs.ia_valid |= ATTR_UID; newattrs.ia_uid = uid; } if (group != (gid_t) -1) { if (!gid_valid(gid)) return -EINVAL; newattrs.ia_valid |= ATTR_GID; newattrs.ia_gid = gid; } if (!S_ISDIR(inode->i_mode)) newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; mutex_lock(&inode->i_mutex); error = security_path_chown(path, uid, gid); if (!error) error = notify_change(path->dentry, &newattrs, &delegated_inode); mutex_unlock(&inode->i_mutex); if (delegated_inode) { error = break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; } return error; }
/** * e_data_cal_view_notify_objects_modified: * @query: A query object. * @objects: List of modified objects. * * Notifies all query listeners of the modification of a list of objects. */ void e_data_cal_view_notify_objects_modified (EDataCalView *view, const GList *objects) { EDataCalViewPrivate *priv; const GList *l; g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view)); priv = view->priv; if (objects == NULL) return; g_mutex_lock (priv->pending_mutex); for (l = objects; l; l = l->next) { /* TODO: send add/remove/change as relevant, based on ->ids */ notify_change (view, e_util_utf8_make_valid (l->data)); } g_mutex_unlock (priv->pending_mutex); }
asmlinkage int sys_fchmod(unsigned int fd, mode_t mode) { struct inode * inode; struct file * file; struct iattr newattrs; if (fd >= NR_OPEN || !(file = current->files->fd[fd])) return -EBADF; if (!(inode = file->f_inode)) return -ENOENT; if (IS_RDONLY(inode)) return -EROFS; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) return -EPERM; if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; inode->i_dirt = 1; return notify_change(inode, &newattrs); }
static int chmod_common(struct path *path, umode_t mode) { struct inode *inode = path->dentry->d_inode; struct iattr newattrs; int error; error = mnt_want_write(path->mnt); if (error) return error; mutex_lock(&inode->i_mutex); error = security_path_chmod(path, mode); if (error) goto out_unlock; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; error = notify_change(path->dentry, &newattrs); out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(path->mnt); return error; }
int ovl_setattr(struct dentry *dentry, struct iattr *attr) { int err; struct dentry *upperdentry; err = ovl_want_write(dentry); if (err) goto out; upperdentry = ovl_dentry_upper(dentry); if (upperdentry) { mutex_lock(&upperdentry->d_inode->i_mutex); err = notify_change(upperdentry, attr, NULL); mutex_unlock(&upperdentry->d_inode->i_mutex); } else { err = ovl_copy_up_last(dentry, attr, false); } ovl_drop_write(dentry); out: return err; }
__NOMIPS16 #endif asmlinkage long sys_utime(char * filename, struct utimbuf * times) { int error; struct nameidata nd; struct inode * inode; struct iattr newattrs; error = user_path_walk(filename, &nd); if (error) goto out; inode = nd.dentry->d_inode; error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; /* Don't worry, the checks are done in inode_change_ok() */ newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; if (times) { error = get_user(newattrs.ia_atime, ×->actime); if (!error) error = get_user(newattrs.ia_mtime, ×->modtime); if (error) goto dput_and_out; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; } else { if (current->fsuid != inode->i_uid && (error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; } error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); out: return error; }
int do_truncate(struct inode *inode, unsigned long length) { int error; struct iattr newattrs; down(&inode->i_sem); newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; error = notify_change(inode, &newattrs); if (!error) { /* truncate virtual mappings of this file */ vmtruncate(inode, length); if (inode->i_op && inode->i_op->truncate) inode->i_op->truncate(inode); #ifdef CONFIG_OSFMACH3 if (inode->i_mem_object && inode->i_mem_object->imo_cacheable) inode_pager_uncache(inode); #endif /* CONFIG_OSFMACH3 */ } up(&inode->i_sem); return error; }
__NOMIPS16 #endif asmlinkage long sys_utimes(char * filename, struct timeval * utimes) { int error; struct nameidata nd; struct inode * inode; struct iattr newattrs; error = user_path_walk(filename, &nd); if (error) goto out; inode = nd.dentry->d_inode; error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; /* Don't worry, the checks are done in inode_change_ok() */ newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; if (utimes) { struct timeval times[2]; error = -EFAULT; if (copy_from_user(×, utimes, sizeof(times))) goto dput_and_out; newattrs.ia_atime = times[0].tv_sec; newattrs.ia_mtime = times[1].tv_sec; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; } else { if ((error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; } error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); out: return error; }
int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, struct file *filp) { int err; struct iattr newattrs; /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */ if (length < 0) return -EINVAL; newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | time_attrs; if (filp) { newattrs.ia_file = filp; newattrs.ia_valid |= ATTR_FILE; } mutex_lock(&dentry->d_inode->i_mutex); err = notify_change(dentry, &newattrs); mutex_unlock(&dentry->d_inode->i_mutex); return err; }
int sys_write(unsigned int fd, char *buf, size_t count) { register struct file_operations *fop; struct file *file; register struct inode *inode; int written; if (((written = fd_check(fd, buf, count, FMODE_WRITE, &file)) == 0) && (count != 0)) { written = -EINVAL; fop = file->f_op; if (fop->write) { inode = file->f_inode; /* * If data has been written to the file, remove the setuid and * the setgid bits. We do it anyway otherwise there is an * extremely exploitable race - does your OS get it right |-> * * Set ATTR_FORCE so it will always be changed. */ if (!suser() && (inode->i_mode & (S_ISUID | S_ISGID))) { #ifdef USE_NOTIFY_CHANGE struct iattr newattrs; newattrs.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID); newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_FORCE; notify_change(inode, &newattrs); #else inode->i_mode = inode->i_mode & ~(S_ISUID | S_ISGID); #endif } written = (int) fop->write(inode, file, buf, count); schedule(); } } return written; }
asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) { struct inode * inode; struct dentry * dentry; struct file * file; int err = -EBADF; struct iattr newattrs; file = fget(fd); if (!file) goto out; dentry = file->f_path.dentry; inode = dentry->d_inode; audit_inode(NULL, dentry); err = mnt_want_write(file->f_path.mnt); if (err) goto out_putf; err = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out_drop_write; mutex_lock(&inode->i_mutex); if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); mutex_unlock(&inode->i_mutex); out_drop_write: mnt_drop_write(file->f_path.mnt); out_putf: fput(file); out: return err; }
SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) { struct path path; struct inode *inode; int error; struct iattr newattrs; error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); if (error) goto out; //ASUS_BSP +++ Jimmy,Josh "remove fuse" if(strcmp(path.mnt->mnt_mountpoint->d_iname,"sdcard")==0){ error = -ENOSYS; goto dput_and_out; } //ASUS_BSP --- Jimmy,Josh "remove fuse" inode = path.dentry->d_inode; error = mnt_want_write(path.mnt); if (error) goto dput_and_out; mutex_lock(&inode->i_mutex); error = security_path_chmod(path.dentry, path.mnt, mode); if (error) goto out_unlock; if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; error = notify_change(path.dentry, &newattrs); out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); dput_and_out: path_put(&path); out: return error; }
/** * e_data_book_view_notify_update: * @book_view: an #EDataBookView * @contact: an #EContact * * Notify listeners that @contact has changed. This can * trigger an add, change or removal event depending on * whether the change causes the contact to start matching, * no longer match, or stay matching the query specified * by @book_view. **/ void e_data_book_view_notify_update (EDataBookView *book_view, EContact *contact) { EDataBookViewPrivate *priv = book_view->priv; gboolean currently_in_view, want_in_view; const gchar *id; gchar *vcard; if (!priv->running) return; g_mutex_lock (priv->pending_mutex); id = e_contact_get_const (contact, E_CONTACT_UID); currently_in_view = id_is_in_view (book_view, id); want_in_view = e_book_backend_sexp_match_contact (priv->card_sexp, contact); if (want_in_view) { vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); if (currently_in_view) notify_change (book_view, vcard); else notify_add (book_view, id, vcard); g_free (vcard); } else { if (currently_in_view) notify_remove (book_view, id); /* else nothing; we're removing a card that wasn't there */ } g_mutex_unlock (priv->pending_mutex); }
/* Determine the mode based on the copyup flags, and the existing dentry. */ static int copyup_permissions(struct super_block *sb, struct dentry *old_hidden_dentry, struct dentry *new_hidden_dentry) { struct iattr newattrs; int err; print_entry_location(); newattrs.ia_atime = old_hidden_dentry->d_inode->i_atime; newattrs.ia_mtime = old_hidden_dentry->d_inode->i_mtime; newattrs.ia_ctime = old_hidden_dentry->d_inode->i_ctime; newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET; if (IS_SET(sb, COPYUP_CURRENT_USER)) { /* current file permission */ newattrs.ia_mode = ~current->fs->umask & S_IRWXUGO; newattrs.ia_valid |= ATTR_FORCE | ATTR_MODE; } else { /* original mode of old file */ newattrs.ia_mode = old_hidden_dentry->d_inode->i_mode; newattrs.ia_gid = old_hidden_dentry->d_inode->i_gid; newattrs.ia_uid = old_hidden_dentry->d_inode->i_uid; newattrs.ia_valid |= ATTR_FORCE | ATTR_GID | ATTR_UID | ATTR_MODE; } if (newattrs.ia_valid & ATTR_MODE) { newattrs.ia_mode = (newattrs.ia_mode & S_IALLUGO) | (old_hidden_dentry-> d_inode-> i_mode & ~S_IALLUGO); } err = notify_change(new_hidden_dentry, &newattrs); print_exit_status(err); return err; }
int ovl_setattr(struct dentry *dentry, struct iattr *attr) { struct dentry *upperdentry; int err; if ((attr->ia_valid & ATTR_SIZE) && !ovl_dentry_upper(dentry)) err = ovl_copy_up_truncate(dentry, attr->ia_size); else err = ovl_copy_up(dentry); if (err) return err; upperdentry = ovl_dentry_upper(dentry); if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) attr->ia_valid &= ~ATTR_MODE; mutex_lock(&upperdentry->d_inode->i_mutex); err = notify_change(upperdentry, attr); mutex_unlock(&upperdentry->d_inode->i_mutex); return err; }
SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) { struct inode * inode; struct dentry * dentry; struct file * file; int err = -EBADF; struct iattr newattrs; file = fget(fd); if (!file) goto out; dentry = file->f_path.dentry; inode = dentry->d_inode; audit_inode(NULL, dentry); err = mnt_want_write_file(file); if (err) goto out_putf; mutex_lock(&inode->i_mutex); err = security_path_chmod(dentry, file->f_vfsmnt, mode); if (err) goto out_unlock; if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(file->f_path.mnt); out_putf: fput(file); out: return err; }