Beispiel #1
0
func findPathRootId(dir *C.DIR) (uint64, error) {
	fd := getDirFd(dir)

	var args C.struct_btrfs_ioctl_ino_lookup_args
	args.objectid = C.BTRFS_FIRST_FREE_OBJECTID

	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, C.BTRFS_IOC_INO_LOOKUP, uintptr(unsafe.Pointer(&args)))
	if errno != 0 {
		return 0, fmt.Errorf("Failed to perform the inode lookup %v", errno.Error())
	}

	return uint64(args.treeid), nil
}
Beispiel #2
0
func (ila *inodeLookupArgs) C() C.struct_btrfs_ioctl_ino_lookup_args {
	var args C.struct_btrfs_ioctl_ino_lookup_args
	args.objectid = C.__u64(ila.ObjectID)
	args.treeid = C.__u64(ila.TreeID)
	if ila.Name != "" {
		str := [C.BTRFS_INO_LOOKUP_PATH_MAX]C.char{}
		for i := 0; i < len(ila.Name) && i < C.BTRFS_INO_LOOKUP_PATH_MAX; i++ {
			str[i] = C.char(ila.Name[i])
		}
		args.name = str
	}
	return args
}
Beispiel #3
0
func inodeLookup(dirpath string) (*inodeLookupArgs, error) {
	dir, err := openDir(dirpath)
	if err != nil {
		return nil, err
	}
	defer closeDir(dir)
	var inoArgs C.struct_btrfs_ioctl_ino_lookup_args
	inoArgs.objectid = C.BTRFS_FIRST_FREE_OBJECTID
	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_INO_LOOKUP,
		uintptr(unsafe.Pointer(&inoArgs)))
	if errno != 0 {
		return nil, fmt.Errorf("Failed to lookup btrfs inode: %v", errno.Error())
	}
	return newInodeLookupArgs(inoArgs), nil
}
Beispiel #4
0
func findRootGen(dir *C.DIR) (uint64, error) {
	fd := getDirFd(dir)

	var maxFound uint64 = 0
	var inoArgs C.struct_btrfs_ioctl_ino_lookup_args
	var args C.struct_btrfs_ioctl_search_args
	var sk *C.struct_btrfs_ioctl_search_key = &args.key
	var sh C.struct_btrfs_ioctl_search_header

	inoArgs.objectid = C.BTRFS_FIRST_FREE_OBJECTID

	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, C.BTRFS_IOC_INO_LOOKUP, uintptr(unsafe.Pointer(&inoArgs)))
	if errno != 0 {
		return 0, fmt.Errorf("Failed to perform the inode lookup %v", errno.Error())
	}

	sk.tree_id = 1
	sk.min_objectid = inoArgs.treeid
	sk.max_objectid = inoArgs.treeid
	sk.max_type = C.BTRFS_ROOT_ITEM_KEY
	sk.min_type = C.BTRFS_ROOT_ITEM_KEY
	sk.max_offset = math.MaxUint64
	sk.max_transid = math.MaxUint64
	sk.nr_items = 4096

	for {
		_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, C.BTRFS_IOC_TREE_SEARCH, uintptr(unsafe.Pointer(&args)))
		if errno != 0 {
			return 0, fmt.Errorf("Failed to perform the search %v", errno.Error())
		}

		if sk.nr_items == 0 {
			break
		}

		var off uintptr = 0

		for i := C.__u32(0); i < sk.nr_items; i++ {
			var item *C.struct_btrfs_root_item

			C.memcpy(unsafe.Pointer(&sh), addptr(unsafe.Pointer(&args.buf), off), C.sizeof_struct_btrfs_ioctl_search_header)
			off += C.sizeof_struct_btrfs_ioctl_search_header

			item = (*C.struct_btrfs_root_item)(unsafe.Pointer(&args.buf[off]))
			off += uintptr(sh.len)

			sk.min_objectid = sh.objectid
			sk.min_type = sh._type
			sk.min_offset = sh.offset

			if sh.objectid > inoArgs.treeid {
				break
			}

			if sh.objectid == inoArgs.treeid && sh._type == C.BTRFS_ROOT_ITEM_KEY {
				rootGeneration := item.generation
				if maxFound < uint64(rootGeneration) {
					maxFound = uint64(rootGeneration)
				}
			}
		}

		if sk.min_offset < math.MaxUint64 {
			sk.min_offset++
		} else {
			break
		}

		if sk.min_type != C.BTRFS_ROOT_ITEM_KEY {
			break
		}
		if sk.min_objectid != inoArgs.treeid {
			break
		}

	}

	return maxFound, nil
}