func (fe *fileEntry) open(name string, length int64) (err os.Error) { fe.length = length fe.fd, err = os.Open(name, os.O_RDWR|os.O_CREAT, 0666) if err != nil { return } errno := syscall.Truncate(name, length) if errno != 0 { err = os.NewError("Could not truncate file.") } return }
// Truncate changes the size of the named file. // If the file is a symbolic link, it changes the size of the link's target. // If there is an error, it will be of type *PathError. func Truncate(name string, size int64) error { if e := syscall.Truncate(name, size); e != nil { return &PathError{"truncate", name, e} } return nil }
// Truncate changes the size of the named file. // If the file is a symbolic link, it changes the size of the link's target. func Truncate(name string, size int64) Error { if e := syscall.Truncate(name, size); e != 0 { return &PathError{"truncate", name, Errno(e)} } return nil }
func (constor *Constor) SetAttr(input *fuse.SetAttrIn, out *fuse.AttrOut) fuse.Status { var err error uid := -1 gid := -1 inode := constor.inodemap.findInodePtr(input.NodeId) if inode == nil { constor.error("inode nil") return fuse.EIO } constor.log("%s %d", inode.id, input.Valid) // if ((input.Valid & fuse.FATTR_FH) !=0) && ((input.Valid & (fuse.FATTR_ATIME | fuse.FATTR_MTIME)) == 0) { if ((input.Valid & fuse.FATTR_FH) != 0) && ((input.Valid & fuse.FATTR_SIZE) != 0) { ptr := uintptr(input.Fh) F := constor.getfd(ptr) if F == nil { constor.error("F == nil for %s", inode.id) return fuse.EIO } if F.layer != 0 && inode.layer == -1 { /* FIXME handle this valid case */ // file is in lower layer, opened, deleted, setattr-called constor.error("FSetAttr F.layer=%d inode.layer=%d", F.layer, inode.layer) return fuse.EIO } if F.layer != 0 && inode.layer != 0 { err := constor.copyup(inode) if err != nil { constor.error("copyup failed for %s - %s", inode.id, err) return fuse.ToStatus(err) } path := constor.getPath(0, inode.id) syscall.Close(F.fd) fd, err := syscall.Open(path, F.flags, 0) if err != nil { constor.error("open failed on %s - %s", path, err) return fuse.ToStatus(err) } F.fd = fd F.layer = 0 constor.log("reset fd for %s", path) } else if F.layer != 0 && inode.layer == 0 { // when some other process already has done a copyup syscall.Close(F.fd) path := constor.getPath(0, inode.id) fd, err := syscall.Open(path, F.flags, 0) if err != nil { constor.error("open failed on %s - %s", path, err) return fuse.ToStatus(err) } F.fd = fd F.layer = 0 constor.log("reset fd for %s", path) } if F.layer != 0 { constor.error("layer not 0") return fuse.EIO } if input.Valid&fuse.FATTR_MODE != 0 { permissions := uint32(07777) & input.Mode err = syscall.Fchmod(F.fd, permissions) if err != nil { constor.error("Fchmod failed on %s - %d : %s", F.id, permissions, err) return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_UID) != 0 { uid = int(input.Uid) } if input.Valid&(fuse.FATTR_GID) != 0 { gid = int(input.Gid) } if input.Valid&(fuse.FATTR_UID|fuse.FATTR_GID) != 0 { err = syscall.Fchown(F.fd, uid, gid) if err != nil { constor.error("Fchown failed on %s - %d %d : %s", F.id, uid, gid, err) return fuse.ToStatus(err) } } if input.Valid&fuse.FATTR_SIZE != 0 { err := syscall.Ftruncate(F.fd, int64(input.Size)) if err != nil { constor.error("Ftruncate failed on %s - %d : %s", F.id, input.Size, err) return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_ATIME|fuse.FATTR_MTIME|fuse.FATTR_ATIME_NOW|fuse.FATTR_MTIME_NOW) != 0 { now := time.Now() var tv []syscall.Timeval tv = make([]syscall.Timeval, 2) if input.Valid&fuse.FATTR_ATIME_NOW != 0 { tv[0].Sec = now.Unix() tv[0].Usec = now.UnixNano() / 1000 } else { tv[0].Sec = int64(input.Atime) tv[0].Usec = int64(input.Atimensec / 1000) } if input.Valid&fuse.FATTR_MTIME_NOW != 0 { tv[1].Sec = now.Unix() tv[1].Usec = now.UnixNano() / 1000 } else { tv[1].Sec = int64(input.Atime) tv[1].Usec = int64(input.Atimensec / 1000) } err := syscall.Futimes(F.fd, tv) if err != nil { constor.error("Futimes failed on %s : %s", F.id, err) return fuse.ToStatus(err) } } stat := syscall.Stat_t{} err = syscall.Fstat(F.fd, &stat) if err != nil { constor.error("Fstat failed on %s : %s", F.id, err) return fuse.ToStatus(err) } attr := (*fuse.Attr)(&out.Attr) attr.FromStat(&stat) attr.Ino = idtoino(inode.id) return fuse.OK } if inode.layer == -1 { return fuse.ENOENT } if inode.layer != 0 { err = constor.copyup(inode) if err != nil { constor.error("copyup failed for %s - %s", inode.id, err) return fuse.ToStatus(err) } } stat := syscall.Stat_t{} path := constor.getPath(0, inode.id) // just to satisfy PJD tests if input.Valid == 0 { err = syscall.Lchown(path, uid, gid) if err != nil { return fuse.ToStatus(err) } } if input.Valid&fuse.FATTR_MODE != 0 { permissions := uint32(07777) & input.Mode err = syscall.Chmod(path, permissions) if err != nil { constor.error("Lchmod failed on %s - %d : %s", path, permissions, err) return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_UID) != 0 { uid = int(input.Uid) } if input.Valid&(fuse.FATTR_GID) != 0 { gid = int(input.Gid) } if input.Valid&(fuse.FATTR_UID|fuse.FATTR_GID) != 0 { constor.log("%s %d %d", path, uid, gid) err = syscall.Lchown(path, uid, gid) if err != nil { constor.error("Lchown failed on %s - %d %d : %s", path, uid, gid, err) return fuse.ToStatus(err) } } if input.Valid&fuse.FATTR_SIZE != 0 { err = syscall.Truncate(path, int64(input.Size)) if err != nil { constor.error("Truncate failed on %s - %d : %s", path, input.Size, err) return fuse.ToStatus(err) } } if input.Valid&(fuse.FATTR_ATIME|fuse.FATTR_MTIME|fuse.FATTR_ATIME_NOW|fuse.FATTR_MTIME_NOW) != 0 { now := time.Now() var atime *time.Time var mtime *time.Time if input.Valid&fuse.FATTR_ATIME_NOW != 0 { atime = &now } else { t := time.Unix(int64(input.Atime), int64(input.Atimensec)) atime = &t } if input.Valid&fuse.FATTR_MTIME_NOW != 0 { mtime = &now } else { t := time.Unix(int64(input.Mtime), int64(input.Mtimensec)) mtime = &t } fi, err := os.Lstat(path) if err != nil { return fuse.ToStatus(err) } if fi.Mode()&os.ModeSymlink != os.ModeSymlink { // FIXME: there is no Lchtimes err = os.Chtimes(path, *atime, *mtime) if err != nil { constor.error("Chtimes failed on %s : %s", path, err) return fuse.ToStatus(err) } } else { constor.error("Chtimes on Symlink not supported") } } attr := (*fuse.Attr)(&out.Attr) err = constor.Lstat(inode.layer, inode.id, &stat) if err != nil { constor.error("Lstat failed on %s : %s", inode.id, err) return fuse.ToStatus(err) } attr.FromStat(&stat) attr.Ino = stat.Ino return fuse.ToStatus(err) }