예제 #1
0
func (constor *Constor) Open(input *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) {
	pathl, err := constor.getPath(input.NodeId)
	if err != nil {
		constor.error("%s", err)
		return fuse.ToStatus(err)
	}
	inode, err := constor.inodemap.findInode(input.NodeId)
	if err != nil {
		constor.error("%s", err)
		return fuse.ToStatus(err)
	}
	constor.log("%s %d %d %d", pathl, input.Flags, input.Uid, input.Gid)
	fd, err := syscall.Open(pathl, int(input.Flags), 0)
	if err != nil {
		constor.error("%s", err)
		return fuse.ToStatus(err)
	}
	F := new(FD)
	F.fd = fd
	F.flags = int(input.Flags)
	F.layer = inode.layer
	constor.putfd(F)
	out.Fh = uint64(uintptr(unsafe.Pointer(F)))
	out.OpenFlags = 0
	constor.log("%d", out.Fh)
	return fuse.OK
}
예제 #2
0
func (constor *Constor) Open(input *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) {
	inode := constor.inodemap.findInodePtr(input.NodeId)
	if inode == nil {
		return fuse.ENOENT
	}
	path := constor.getPath(inode.layer, inode.id)
	constor.log("%s %d", path, input.Flags)
	fd, err := syscall.Open(path, int(input.Flags), 0)
	if err != nil {
		constor.error("open failed %s : %s", path, err)
		return fuse.ToStatus(err)
	}
	F := new(FD)
	F.fd = fd
	F.flags = int(input.Flags)
	F.layer = inode.layer
	F.id = inode.id
	F.pid = input.Pid
	constor.putfd(F)
	out.Fh = uint64(uintptr(unsafe.Pointer(F)))
	if input.Flags&syscall.O_DIRECT != 0 {
		out.OpenFlags = fuse.FOPEN_DIRECT_IO
	} else {
		out.OpenFlags = fuse.FOPEN_KEEP_CACHE
	}

	constor.log("%d", out.Fh)
	return fuse.OK
}
예제 #3
0
파일: fsops.go 프로젝트: eliq/go-fuse
func (c *rawBridge) Open(input *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) {
	node := c.toInode(input.NodeId)
	f, code := node.fsInode.Open(input.Flags, &input.Context)
	if !code.Ok() || f == nil {
		return code
	}
	h, opened := node.mount.registerFileHandle(node, nil, f, input.Flags)
	out.OpenFlags = opened.FuseFlags
	out.Fh = h
	return fuse.OK
}
예제 #4
0
파일: fsops.go 프로젝트: eliq/go-fuse
func (c *rawBridge) OpenDir(input *fuse.OpenIn, out *fuse.OpenOut) (code fuse.Status) {
	node := c.toInode(input.NodeId)
	stream, err := node.fsInode.OpenDir(&input.Context)
	if err != fuse.OK {
		return err
	}
	stream = append(stream, node.getMountDirEntries()...)
	de := &connectorDir{
		node: node.Node(),
		stream: append(stream,
			fuse.DirEntry{Mode: fuse.S_IFDIR, Name: "."},
			fuse.DirEntry{Mode: fuse.S_IFDIR, Name: ".."}),
		rawFS: c,
	}
	h, opened := node.mount.registerFileHandle(node, de, nil, input.Flags)
	out.OpenFlags = opened.FuseFlags
	out.Fh = h
	return fuse.OK
}
예제 #5
0
func (constor *Constor) OpenDir(input *fuse.OpenIn, out *fuse.OpenOut) (code fuse.Status) {
	constor.log("%d", input.NodeId)
	path, err := constor.dentrymap.getPath(input.NodeId)
	if err != nil {
		return fuse.ToStatus(err)
	}
	entries := map[string]DirEntry{}
	for li, layer := range constor.layers {
		f, err := os.Open(Path.Join(layer, path))
		if err != nil {
			continue
		}
		infos, _ := f.Readdir(0)
		for i := range infos {
			// workaround forhttps://code.google.com/p/go/issues/detail?id=5960
			if infos[i] == nil {
				continue
			}
			name := infos[i].Name()
			if _, ok := entries[name]; ok {
				// skip if the file was in upper layer
				continue
			}

			mode := infos[i].Mode()
			stat := infos[i].Sys().(*syscall.Stat_t)
			d := DirEntry{
				Name: name,
				Mode: uint32(mode),
				Ino:  stat.Ino,
			}
			if li == 0 {
				err := constor.Lstat(Path.Join(path, name), stat)
				if err == nil {
					d.Ino = stat.Ino
				}
			}
			d.Stat = *stat
			pathl := Path.Join(constor.layers[li], path, name)
			if constor.isdeleted(pathl) {
				d.Deleted = true
			}
			entries[name] = d
		}
		f.Close()
	}
	output := make([]DirEntry, 0, 500)

	for _, d := range entries {
		if d.Deleted {
			continue
		}
		output = append(output, d)
	}
	stat := syscall.Stat_t{}
	err = constor.Lstat(path, &stat)
	d := DirEntry{
		Name: ".",
		Mode: stat.Mode,
		Ino:  stat.Ino,
	}
	output = append(output, d)

	err = constor.Lstat(Path.Join(path, ".."), &stat)
	d = DirEntry{
		Name: "..",
		Mode: stat.Mode,
		Ino:  stat.Ino,
	}
	output = append(output, d)

	for i, _ := range output {
		output[i].Offset = uint64(i) + 1
	}
	F := new(FD)
	F.stream = output
	constor.putfd(F)
	out.Fh = uint64(uintptr(unsafe.Pointer(F)))
	out.OpenFlags = 0
	return fuse.OK
}
예제 #6
0
func (constor *Constor) OpenDir(input *fuse.OpenIn, out *fuse.OpenOut) (code fuse.Status) {
	inode := constor.inodemap.findInodePtr(input.NodeId)
	if inode == nil {
		constor.log("inode == nil for %d", input.NodeId)
		return fuse.ENOENT
	}
	constor.log("%s", inode.id)
	entries := map[string]DirEntry{}
	for li, _ := range constor.layers {
		path := constor.getPath(li, inode.id)
		stat := syscall.Stat_t{}
		err := syscall.Lstat(path, &stat)
		if err != nil {
			// continue aggregating upper layers
			continue
		}
		if (stat.Mode & syscall.S_IFMT) != syscall.S_IFDIR {
			constor.error("Not a dir: %s", path)
			break
		}

		f, err := os.Open(path)
		if err != nil {
			constor.error("Open failed on %s", path)
			break
		}
		infos, _ := f.Readdir(0) // reads all entries except "." and ".."
		for i := range infos {
			// workaround forhttps://code.google.com/p/go/issues/detail?id=5960
			if infos[i] == nil {
				continue
			}
			name := infos[i].Name()
			if _, ok := entries[name]; ok {
				// skip if the file was in upper layer
				continue
			}
			d := DirEntry{
				Name: name,
				Mode: uint32(infos[i].Mode()),
			}
			if constor.isdeleted(Path.Join(path, name), infos[i].Sys().(*syscall.Stat_t)) {
				d.Deleted = true
			} else {
				id, err := constor.getid(li, inode.id, name)
				if err != nil {
					constor.error("getid failed on %d %s %s", li, inode.id, name)
					continue
				}
				d.Ino = idtoino(id)

			}
			entries[name] = d
		}
		f.Close()
	}
	output := make([]DirEntry, 0, 500)

	for _, d := range entries {
		if d.Deleted {
			continue
		}
		output = append(output, d)
	}
	d := DirEntry{
		Name: ".",
		Mode: syscall.S_IFDIR,
		Ino:  idtoino(inode.id),
	}
	output = append(output, d)

	// FIXME: take care of ".." entry
	// err = constor.Lstat(Path.Join(path, ".."), &stat)
	// d = DirEntry{
	// 	Name: "..",
	// 	Mode: syscall.S_IFDIR,
	// }
	// output = append(output, d)

	for i, _ := range output {
		output[i].Offset = uint64(i) + 1
	}
	fmt.Println(output)
	F := new(FD)
	if F == nil {
		return fuse.ToStatus(syscall.ENOMEM)
	}
	F.stream = output
	constor.putfd(F)
	out.Fh = uint64(uintptr(unsafe.Pointer(F)))
	out.OpenFlags = 0
	return fuse.OK
}