// Create adds either a synthetic dir or file, depending on the file // permissions, if the create is permitted and a file with that name doesn't // already exist. It also updates mtime, mtime and version for the dir. func (d *SyntheticDir) Create(user, name string, perms qp.FileMode) (File, error) { d.Lock() defer d.Unlock() owner := d.UID == user if !PermCheck(owner, false, d.Permissions, qp.OWRITE) { return nil, ErrPermissionDenied } _, ok := d.Tree[name] if ok { return nil, ErrFileAlreadyExists } var f File if perms&qp.DMDIR != 0 { perms = perms & (^qp.FileMode(0777) | (d.Permissions & 0777)) f = NewSyntheticDir(name, perms, d.UID, d.GID) } else { perms = perms & (^qp.FileMode(0666) | (d.Permissions & 0666)) f = NewSyntheticFile(name, perms, d.UID, d.GID) } d.Tree[name] = f d.Mtime = time.Now() d.Atime = d.Mtime d.Version++ return f, nil }
func emptyStat() qp.Stat { return qp.Stat{ Type: ^uint16(0), Dev: ^uint32(0), Mode: ^qp.FileMode(0), Atime: ^uint32(0), Mtime: ^uint32(0), Length: ^uint64(0), } }
// Create creates either a file or a directory at the specified path. It fails // if the file already exists, or permissions did not permit it. func (c *SimpleClient) Create(name string, directory bool) error { if c.root == nil { return ErrSimpleClientNotStarted } dir := path.Dir(name) file := path.Base(name) fid, _, err := c.walkTo(dir) if err != nil { return err } defer fid.Clunk() perms := qp.FileMode(0755) if directory { perms |= qp.DMDIR } _, _, err = fid.Create(file, perms, qp.OREAD) if err != nil { return err } return nil }
func setStat(user string, e trees.File, parent trees.Dir, nstat qp.Stat) error { ostat, err := e.Stat() if err != nil { return err } length := false name := false mode := false owner := false if nstat.Type != ^uint16(0) && nstat.Type != ostat.Type { return errors.New("it is illegal to modify type") } if nstat.Dev != ^uint32(0) && nstat.Dev != ostat.Dev { return errors.New("it is illegal to modify dev") } if nstat.MUID != "" && nstat.MUID != ostat.MUID { return errors.New("it is illegal to modify muid") } if nstat.Atime != ^uint32(0) && nstat.Atime != ostat.Atime { return errors.New("it is illegal to modify atime") } if parent == nil && nstat.Name != "" && nstat.Name != ostat.Name { return errors.New("it is illegal to rename root") } if nstat.Length != ^uint64(0) && nstat.Length != ostat.Length { if ostat.Mode&qp.DMDIR != 0 { return errors.New("cannot set length of directory") } if nstat.Length > ostat.Length { return errors.New("cannot extend length") } length = true } if nstat.Name != "" && nstat.Name != ostat.Name { name = true } if (nstat.UID != "" && nstat.UID != ostat.UID) || (nstat.GID != "" && nstat.GID != ostat.GID) { owner = true } if nstat.Mode != ^qp.FileMode(0) && nstat.Mode != ostat.Mode { mode = true } if nstat.Mtime != ^uint32(0) && nstat.Mtime != ostat.Mtime { // We ignore mtime changes ATM. Only owner can change mtime. } if mode { if err := e.SetMode(user, ostat.Mode&qp.DMDIR | nstat.Mode & ^qp.DMDIR); err != nil { return err } } if owner { if err := e.SetOwner(user, nstat.UID, nstat.GID); err != nil { e.SetMode(user, ostat.Mode) return err } } if name { if err := parent.Rename(user, ostat.Name, nstat.Name); err != nil { e.SetMode(user, ostat.Mode) e.SetOwner(user, ostat.UID, ostat.GID) return err } } if length { if err := e.SetLength(user, nstat.Length); err != nil { e.SetMode(user, ostat.Mode) e.SetOwner(user, ostat.UID, ostat.GID) parent.Rename(user, nstat.Name, ostat.Name) return err } } return nil }