/* This should attempt a utimes call for the user specified by CRED on node NODE, to change the atime to ATIME and the mtime to MTIME. */ error_t netfs_attempt_utimes (struct iouser *cred, struct node *node, struct timespec *atime, struct timespec *mtime) { error_t err = procfs_refresh_node (node); int flags = TOUCH_CTIME; if (! err) err = fshelp_isowner (&node->nn_stat, cred); if (! err) { if (atime) node->nn_stat.st_atim = *atime; else flags |= TOUCH_ATIME; if (mtime) node->nn_stat.st_mtim = *mtime; else flags |= TOUCH_MTIME; fshelp_touch (&node->nn_stat, flags, procfs_maptime); } return err; }
/* This should attempt a chmod call for the user specified by CRED on node NODE, to change the mode to MODE. Unlike the normal Unix and Hurd meaning of chmod, this function is also used to attempt to change files into other types. If such a transition is attempted which is impossible, then return EOPNOTSUPP. */ error_t netfs_attempt_chmod (struct iouser *cred, struct node *node, mode_t mode) { error_t err = 0; debug(""); if (node->nn->ln == NULL) return EOPNOTSUPP; mode &= ~S_ITRANS; err = fshelp_isowner (&node->nn->ln->st, cred); if (err) return err; mode |= node->nn->ln->st.st_mode & S_IFMT; node->nn->ln->st.st_mode = mode; fshelp_touch (&node->nn_stat, TOUCH_CTIME, multiplexer_maptime); return err; }
/* Lookup NAME in DIR for USER; set *NODE to the found name upon return. If the name was not found, then return ENOENT. On any error, clear *NODE. (*NODE, if found, should be locked, this call should unlock DIR no matter what.) */ error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, char *name, struct node **node) { error_t err; if (dir->nn->name) err = ENOTDIR; else err = fshelp_access (&dir->nn_stat, S_IEXEC, user); if (! err) { if (strcmp (name, ".") == 0) /* Current directory -- just add an additional reference to DIR and return it. */ { netfs_nref (dir); *node = dir; err = 0; } else if (strcmp (name, "..") == 0) err = EAGAIN; else err = lookup_host (dir->nn->mux, name, node); fshelp_touch (&dir->nn_stat, TOUCH_ATIME, hostmux_maptime); } pthread_mutex_unlock (&dir->lock); if (err) *node = 0; else pthread_mutex_lock (&(*node)->lock); return err; }
/* cvsfs_make_node * * create a struct node* for the specified netnode 'nn'. */ struct node * cvsfs_make_node(struct netnode *nn) { struct node *node; rwlock_writer_lock(&nn->lock); if(nn->node) { /* there already is a node structure, just return another reference * to this one, instead of wasting memory for yet another one */ mutex_lock(&nn->node->lock); netfs_nref(nn->node); mutex_unlock(&nn->node->lock); rwlock_writer_unlock(&nn->lock); return nn->node; } if(! (node = netfs_make_node(nn))) { rwlock_writer_unlock(&nn->lock); return NULL; } /* put timestamp on file */ fshelp_touch(&node->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, cvsfs_maptime); /* initialize stats of new node ... */ node->nn_stat.st_fstype = FSTYPE_MISC; node->nn_stat.st_fsid = stat_template.fsid; node->nn_stat.st_ino = nn->fileno; node->nn_stat.st_mode = stat_template.mode; node->nn_stat.st_nlink = 1; node->nn_stat.st_uid = stat_template.uid; node->nn_stat.st_gid = stat_template.gid; node->nn_stat.st_size = 0; node->nn_stat.st_blksize = 4096; /* is there a better default?? */ node->nn_stat.st_blocks = 0; node->nn_stat.st_author = stat_template.author; if(! nn->revision) { /* we're creating a node for a directory, mark as such! */ node->nn_stat.st_mode |= S_IFDIR; /* since we got a directory we need to supply "executable" * permissions, so our user is enabled to make use of this dir */ if(node->nn_stat.st_mode & S_IRUSR) node->nn_stat.st_mode |= S_IXUSR; if(node->nn_stat.st_mode & S_IRGRP) node->nn_stat.st_mode |= S_IXGRP; if(node->nn_stat.st_mode & S_IROTH) node->nn_stat.st_mode |= S_IXOTH; } else { if(nn->revision->contents && ! config.nostats) { node->nn_stat.st_mode = nn->revision->perm; node->nn_stat.st_size = nn->revision->length; node->nn_stat.st_blocks = (node->nn_stat.st_size >> 9) + 1; node->nn_stat.st_atime = node->nn_stat.st_mtime = node->nn_stat.st_ctime = nn->revision->time; node->nn_stat.st_atime_usec = node->nn_stat.st_mtime_usec = node->nn_stat.st_ctime_usec = 0; } /* well, we're creating a new node for a file ... */ node->nn_stat.st_mode |= S_IFREG; /* for now simply drop all execute permissions, this needs to be fixed, * since CVS support executables, e.g. shell scripts, that we need to * support .... FIXME */ node->nn_stat.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); }