Esempio n. 1
0
// OSX does not have the utimensat syscall neded to implement this properly.
// We do our best to emulate it using futimes.
func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
	tv := make([]syscall.Timeval, 2)
	if a == nil {
		tv[0].Usec = _UTIME_OMIT
	} else {
		tv[0] = timeToTimeval(a)
	}

	if m == nil {
		tv[1].Usec = _UTIME_OMIT
	} else {
		tv[1] = timeToTimeval(m)
	}

	f.lock.Lock()
	err := syscall.Futimes(int(f.File.Fd()), tv)
	f.lock.Unlock()
	return fuse.ToStatus(err)
}
Esempio n. 2
0
func (f *AzukiFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
	tv := make([]syscall.Timeval, 2)
	if a == nil {
		tv[0].Usec = _UTIME_OMIT
	} else {
		n := a.UnixNano()
		tv[0] = syscall.NsecToTimeval(n)
	}

	if m == nil {
		tv[1].Usec = _UTIME_OMIT
	} else {
		n := a.UnixNano()
		tv[1] = syscall.NsecToTimeval(n)
	}

	err := syscall.Futimes(int(f.File.Fd()), tv)
	return fuse.ToStatus(err)
}
Esempio n. 3
0
func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
	var ts = make([]syscall.Timeval, 2)

	if a == nil {
		ts[0].Sec = _UTIME_OMIT
	} else {
		ts[0].Sec = a.Unix()
	}

	if m == nil {
		ts[1].Sec = _UTIME_OMIT
	} else {
		ts[1].Sec = m.Unix()
	}

	f.lock.Lock()
	err := syscall.Futimes(int(f.File.Fd()), ts)
	f.lock.Unlock()
	return fuse.ToStatus(err)
}
Esempio n. 4
0
func (fs *Fs) wstatPost(fid *Fid, cur *Dir, next *Dir) error {

	defer fid.file.unlock()

	// Rename the file.
	if next.Name != "" &&
		next.Name != cur.Name {

		new_path := path.Join(path.Dir(fid.Path), next.Name)
		err := fid.file.rename(fs, fid.Path, new_path)
		if err != nil {
			return err
		}
	}

	// Update our access times.
	atime := cur.Atime
	mtime := cur.Atime
	if next.Atime != math.MaxUint32 {
		atime = next.Atime
	}
	if next.Mtime != math.MaxUint32 {
		mtime = next.Mtime
	}
	if atime != cur.Atime || mtime != cur.Mtime {
		err := syscall.Futimes(
			fid.file.write_fd,
			[]syscall.Timeval{
				syscall.Timeval{int64(atime), 0},
				syscall.Timeval{int64(mtime), 0},
			})
		if err != nil {
			return err
		}
	}

	// Truncate the file.
	if next.Length != math.MaxUint64 &&
		next.Length != cur.Length {
		err := syscall.Ftruncate(fid.file.write_fd, int64(next.Length))
		if err != nil {
			return err
		}
	}

	// Change the owner.
	uid := cur.Uidnum
	gid := cur.Gidnum
	if next.Uidnum != math.MaxUint32 &&
		next.Uidnum != cur.Uidnum {
		uid = next.Uidnum
	}
	if next.Gidnum != math.MaxUint32 &&
		next.Gidnum != cur.Gidnum {
		gid = next.Gidnum
	}
	if uid != cur.Uidnum || gid != cur.Gidnum {
		err := syscall.Fchown(fid.file.write_fd, int(uid), int(gid))
		if err != nil {
			return err
		}
	}

	return nil
}
Esempio n. 5
0
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)
}