Exemple #1
0
func touch(filename string, nacc, nmod int64) (errcnt int) {
	var st syscall.Stat_t
	var ut syscall.Utimbuf

	if e := syscall.Stat(filename, &st); e != 0 {
		if e == syscall.ENOENT {

			if *cflag {
				errcnt++
				return
			}

			var fd int
			defer syscall.Close(fd)

			if fd, e = syscall.Creat(filename, 0666); e != 0 {
				fmt.Fprintf(os.Stderr, "touch: can not create %s\n", filename)
				errcnt += 1
				return
			}

			if e = syscall.Fstat(fd, &st); e != 0 {
				fmt.Fprintf(os.Stderr, "touch: can't stat %s\n", filename)
				errcnt += 1
				return
			}
		} else {
			fmt.Fprintf(os.Stderr, "touch: can't stat %s\n", filename)
			errcnt += 1
			return
		}
	}

	if *aflag {
		ut.Actime = nacc
	} else {
		ut.Actime = st.Atim.Sec
	}

	if *mflag {
		ut.Modtime = nmod
	} else {
		ut.Modtime = st.Mtim.Sec
	}

	if nulltime {
		if e := syscall.Utime(filename, nil); e != 0 {
			fmt.Fprintf(os.Stderr, "touch: unable to touch %s", filename)
			errcnt += 1
		}
	} else {
		if e := syscall.Utime(filename, &ut); e != 0 {
			fmt.Fprintf(os.Stderr, "touch: unable to touch %s", filename)
			errcnt += 1
		}
	}

	return
}
Exemple #2
0
func (constor *Constor) setdeleted(pathl string) error {
	stat := syscall.Stat_t{}
	err := syscall.Stat(pathl, &stat)
	if err != nil {
		fd, err := syscall.Creat(pathl, 0)
		if err != nil {
			return err
		}
		syscall.Close(fd)
	}
	return syscall.Setxattr(pathl, DELXATTR, []byte{49}, 0)
}
Exemple #3
0
func (constor *Constor) Rmdir(header *fuse.InHeader, name string) (code fuse.Status) {
	constor.log("%d %s", header.NodeId, name)
	var stat syscall.Stat_t
	parentino := header.NodeId
	dirpath, err := constor.dentrymap.getPath(parentino)
	if err != nil {
		return fuse.ToStatus(err)
	}
	path := Path.Join(dirpath, name)
	if err := constor.Lstat(path, &stat); err != nil {
		return fuse.ToStatus(err)
	}
	li := constor.getLayer(path)
	if li == -1 {
		return fuse.EIO
	}
	pathlayer0 := Path.Join(constor.layers[0], path)

	if li == 0 {
		// FIXME: make sure the dir is not empty
		// err = os.RemoveAll(pathlayer0)
		err = syscall.Rmdir(pathlayer0)
		if err != nil {
			return fuse.ToStatus(err)
		}
		li = constor.getLayer(path)
	}

	if li > 0 {
		err := constor.createPath(dirpath)
		if err != nil {
			return fuse.ToStatus(err)
		}
		fd, err := syscall.Creat(pathlayer0, 0)
		if err != nil {
			return fuse.ToStatus(err)
		}
		syscall.Close(fd)
		err = constor.setdeleted(pathlayer0)
		if err != nil {
			return fuse.ToStatus(err)
		}
	}

	dentry, err := constor.dentrymap.findDentry(parentino, stat.Ino)
	if err != nil {
		return fuse.ToStatus(err)
	}
	constor.dentrymap.unhashDentry(dentry)
	return fuse.OK
}
Exemple #4
0
func (constor *Constor) Link(input *fuse.LinkIn, name string, out *fuse.EntryOut) (code fuse.Status) {
	inodeold := constor.inodemap.findInodePtr(input.Oldnodeid)
	if inodeold == nil {
		constor.error("inodeold == nil")
		return fuse.ENOENT
	}
	parent := constor.inodemap.findInodePtr(input.NodeId)
	if parent == nil {
		constor.error("parent == nil")
		return fuse.ENOENT
	}
	constor.log("%s <- %s/%s", inodeold.id, parent.id, name)
	if err := constor.copyup(inodeold); err != nil {
		constor.error("copyup failed for %s - %s", inodeold.id, err)
		return fuse.ToStatus(err)
	}
	if err := constor.copyup(parent); err != nil {
		constor.error("copyup failed for %s - %s", parent.id, err)
		return fuse.ToStatus(err)
	}
	path := constor.getPath(0, parent.id)
	entrypath := Path.Join(path, name)

	if constor.isdeleted(entrypath, nil) {
		if err := syscall.Unlink(entrypath); err != nil {
			constor.error("Unlink %s : %s", entrypath, err)
			return fuse.ToStatus(err)
		}
	}

	if fd, err := syscall.Creat(entrypath, 0); err != nil {
		constor.error("Creat %s : %s", entrypath, err)
		return fuse.ToStatus(err)
	} else {
		syscall.Close(fd)
	}
	id := constor.setid(entrypath, inodeold.id)
	if id == "" {
		constor.error("setid %s : %s", entrypath)
		return fuse.EIO
	}
	if err := constor.inclinkscnt(inodeold.id); err != nil {
		constor.error("inclinkscnt %s : %s", inodeold.id, err)
		return fuse.ToStatus(err)
	}
	return constor.Lookup((*fuse.InHeader)(unsafe.Pointer(input)), name, out)
}
Exemple #5
0
func (constor *Constor) Rename(input *fuse.RenameIn, oldName string, newName string) (code fuse.Status) {
	sendEntryNotify := false
	var inodedel *Inode
	oldParent := constor.inodemap.findInodePtr(input.NodeId)
	if oldParent == nil {
		constor.error("oldParent == nil")
		return fuse.ENOENT
	}
	newParent := constor.inodemap.findInodePtr(input.Newdir)
	if newParent == nil {
		constor.error("newParent == nil")
		return fuse.ENOENT
	}
	if err := constor.copyup(newParent); err != nil {
		constor.error("copyup failed for %s - %s", newParent.id, err)
		return fuse.EIO
	}
	newParentPath := constor.getPath(0, newParent.id)
	newentrypath := Path.Join(newParentPath, newName)
	constor.log("%s %s %s %s", oldParent.id, oldName, newParent.id, newName)
	// remove any entry that existed in the newName's place
	if iddel, err := constor.getid(-1, newParent.id, newName); err == nil {
		if inodedel = constor.inodemap.findInodeId(iddel); inodedel != nil {
			if inodedel.layer == 0 {
				linkcnt, err := constor.declinkscnt(inodedel.id)
				if err != nil {
					constor.error("declinkscnt %s : %s", inodedel.id, err)
					return fuse.ToStatus(err)
				}
				if linkcnt == 0 {
					path := constor.getPath(0, iddel)
					fi, err := os.Lstat(path)
					if err != nil {
						constor.error("Lstat failed on %s", path)
						return fuse.ToStatus(err)
					}
					if fi.IsDir() {
						// FIXME: take care of this situation
						constor.error("path is a directory")
						return fuse.Status(syscall.EEXIST)
					}
					if err := syscall.Unlink(path); err != nil {
						constor.error("Unable to remove %s", path)
						return fuse.ToStatus(err)
					}
					inodedel.layer = -1
				}
			}
			stat := syscall.Stat_t{}
			// FIXME do copyup and declinkscnt
			if err := syscall.Lstat(newentrypath, &stat); err == nil {
				fi, err := os.Lstat(newentrypath)
				if err != nil {
					constor.error("Lstat failed on %s", newentrypath)
					return fuse.ToStatus(err)
				}
				if fi.IsDir() {
					// FIXME: take care of this situation
					constor.error("path is a directory")
					return fuse.Status(syscall.EEXIST)
				}
				if err := syscall.Unlink(newentrypath); err != nil {
					constor.error("Unable to remove %s", newentrypath)
					return fuse.ToStatus(err)
				}
			}
			// inodedel.parentPtr = input.Newdir
			// inodedel.name = newName
			sendEntryNotify = true
			// constor.ms.DeleteNotify(input.Newdir, uint64(uintptr(unsafe.Pointer(inodedel))), newName)
			// constor.ms.EntryNotify(input.Newdir, newName)
		} else {
			constor.error("inodedel == nil for %s %s", newParent.id, newName)
			return fuse.EIO
		}
	}
	// remove any deleted placeholder
	if constor.isdeleted(newentrypath, nil) {
		if err := syscall.Unlink(newentrypath); err != nil {
			constor.error("Unlink %s : %s", newentrypath, err)
			return fuse.ToStatus(err)
		}
	}
	oldid, err := constor.getid(-1, oldParent.id, oldName)
	if err != nil {
		constor.error("getid error %s %s", oldParent.id, oldName)
		return fuse.ToStatus(err)
	}
	oldinode := constor.inodemap.findInodeId(oldid)
	if oldinode == nil {
		constor.error("oldinode == nil for %s", oldid)
		return fuse.ENOENT
	}
	path := constor.getPath(oldinode.layer, oldid)
	fi, err := os.Lstat(path)
	if err != nil {
		constor.error("Lstat %s", path)
		return fuse.ToStatus(err)
	}
	oldParentPath := constor.getPath(0, oldParent.id)
	oldentrypath := Path.Join(oldParentPath, oldName)
	oldstat := syscall.Stat_t{}
	if err := syscall.Lstat(oldentrypath, &oldstat); err == nil {
		if fi.IsDir() {
			if err := syscall.Rmdir(oldentrypath); err != nil {
				constor.error("Rmdir %s : %s", oldentrypath, err)
				return fuse.ToStatus(err)
			}
		} else {
			if err := syscall.Unlink(oldentrypath); err != nil {
				constor.error("Unlink %s : %s", oldentrypath, err)
				return fuse.ToStatus(err)
			}
		}
	}
	if _, err := constor.getid(-1, oldParent.id, oldName); err == nil {
		constor.setdeleted(oldentrypath)
	}
	if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
		err = os.Symlink("placeholder", newentrypath)
		if err != nil {
			constor.error("Symlink %s : %s", newentrypath, err)
			return fuse.ToStatus(err)
		}
	} else if fi.Mode()&os.ModeDir == os.ModeDir {
		err := os.Mkdir(newentrypath, fi.Mode())
		if err != nil {
			constor.error("Mkdir %s : %s", newentrypath, err)
			return fuse.ToStatus(err)
		}
	} else {
		fd, err := syscall.Creat(newentrypath, uint32(fi.Mode()))
		if err != nil {
			constor.error("create %s : %s", newentrypath, err)
			return fuse.ToStatus(err)
		}
		syscall.Close(fd)
	}
	id := constor.setid(newentrypath, oldid)
	if id == "" {
		constor.error("setid %s : %s", newentrypath, err)
		return fuse.EIO
	}
	if sendEntryNotify {
		go func() {
			// FIXME: is this needed?
			constor.ms.DeleteNotify(input.Newdir, uint64(uintptr(unsafe.Pointer(inodedel))), newName)
			constor.ms.DeleteNotify(input.NodeId, uint64(uintptr(unsafe.Pointer(oldinode))), oldName)
		}()
	}
	return fuse.OK
}
Exemple #6
0
func (constor *Constor) Create(input *fuse.CreateIn, name string, out *fuse.CreateOut) (code fuse.Status) {
	flags := 0

	inode := constor.inodemap.findInodePtr(input.NodeId)
	if inode == nil {
		constor.error("inode == nil")
		return fuse.ENOENT
	}
	err := constor.copyup(inode)
	if err != nil {
		constor.error("copyup failed for %s - %s", inode.id, err)
		return fuse.ToStatus(err)
	}
	dirpath := constor.getPath(0, inode.id)
	entrypath := Path.Join(dirpath, name)

	if constor.isdeleted(entrypath, nil) {
		if err := syscall.Unlink(entrypath); err != nil {
			constor.error("Unlink %s : %s", entrypath, err)
			return fuse.ToStatus(err)
		}
	}

	fd, err := syscall.Creat(entrypath, input.Mode)
	if err != nil {
		constor.error("Creat %s : %s", entrypath, err)
		return fuse.ToStatus(err)
	}
	syscall.Close(fd)
	id := constor.setid(entrypath, "")
	if id == "" {
		constor.error("setid %s : %s", entrypath, err)
		return fuse.EIO
	}
	constor.log("%s : %s", entrypath, id)
	if err := constor.createPath(id); err != nil {
		constor.error("createPath %s : %s", id, err)
		return fuse.ToStatus(err)
	}
	path := constor.getPath(0, id)
	if input.Flags != 0 {
		flags = int(input.Flags) | syscall.O_CREAT
	} else {
		flags = syscall.O_CREAT | syscall.O_RDWR | syscall.O_EXCL
	}
	fd, err = syscall.Open(path, flags, input.Mode)
	// fd, err = syscall.Open(path, int(input.Flags), input.Mode)
	if err != nil {
		constor.error("open %s : %s", path, err)
		return fuse.ToStatus(err)
	}
	err = syscall.Chown(path, int(input.Uid), int(input.Gid))
	if err != nil {
		constor.error("Chown %s : %s", path, err)
		return fuse.ToStatus(err)
	}
	F := new(FD)
	F.fd = fd
	F.layer = 0
	F.id = id
	F.pid = input.Pid
	constor.putfd(F)
	if flags&syscall.O_DIRECT != 0 {
		out.OpenFlags = fuse.FOPEN_DIRECT_IO
	} else {
		out.OpenFlags = fuse.FOPEN_KEEP_CACHE
	}

	out.Fh = uint64(uintptr(unsafe.Pointer(F)))
	constor.log("%d", out.Fh)
	return constor.Lookup((*fuse.InHeader)(unsafe.Pointer(input)), name, &out.EntryOut)
}