Exemple #1
0
func huurr(dirpath string) ([]string, error) {
	inoArgs, err := inodeLookup(dirpath)
	if err != nil {
		return nil, err
	}

	var searchKey C.struct_btrfs_ioctl_search_key
	searchKey.min_objectid = C.__u64(inoArgs.TreeID)
	searchKey.max_objectid = C.__u64(inoArgs.TreeID)
	searchKey.min_type = C.BTRFS_ROOT_ITEM_KEY
	searchKey.max_type = C.BTRFS_ROOT_ITEM_KEY
	searchKey.max_offset = (1<<48 - 1)
	searchKey.max_transid = (1<<48 - 1)

	return nil, nil
}
Exemple #2
0
func findUpdatedFiles(dir *C.DIR, rootId, oldestGen uint64) (uint64, error) {
	var maxFound uint64 = 0

	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
	var item *BtrfsFileExtentItem
	var backup BtrfsFileExtentItem

	var foundGen uint64 = 0

	sk.tree_id = C.__u64(rootId)
	sk.max_objectid = math.MaxUint64
	sk.max_offset = math.MaxUint64
	sk.max_transid = math.MaxUint64
	sk.max_type = C.BTRFS_EXTENT_DATA_KEY
	sk.min_transid = C.__u64(oldestGen)
	sk.nr_items = 4096

	fd := getDirFd(dir)

	maxFound, err := findRootGen(dir)
	if err != nil {
		return 0, err
	}

	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 := uint32(0); i < uint32(sk.nr_items); i++ {
			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

			if sh.len == 0 {
				item = &backup
			} else {
				rawItem := (*C.struct_btrfs_file_extent_item)(addptr(unsafe.Pointer(&args.buf), off))
				item, err = NewBtrfsFileExtentItem(rawItem)
				if err != nil {
					return 0, err
				}
			}

			foundGen = item.Generation
			if sh._type == C.BTRFS_EXTENT_DATA_KEY && foundGen >= uint64(oldestGen) {
				// print...
			}

			off += uintptr(sh.len)

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

		sk.nr_items = 4096
		if sk.min_offset < math.MaxUint64 {
			sk.min_offset++
		} else if sk.min_objectid < math.MaxUint64 {
			sk.min_objectid++
			sk.min_offset = 0
			sk.min_type = 0

		} else {
			break
		}
	}

	return maxFound, nil
}
Exemple #3
0
func subvolSearch(dir *C.DIR) /**C.struct_root_lookup,*/ error {
	fd := getDirFd(dir)

	//fmt.Printf("Run list...: %v", fd)

	//var root_lookup *C.struct_root_lookup

	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

	var ref *C.struct_btrfs_root_ref
	var ri *C.struct_btrfs_root_item

	var dirId uint64
	var ogen uint64
	var gen uint64
	var flags uint64
	var t uint64

	var ouuid, puuid, ruuid uuid.UUID
	emptyUUID := uuid.UUID{}

	/* search in the tree of tree roots */
	sk.tree_id = 1

	/*
	 * set the min and max to backref keys.  The search will
	 * only send back this type of key now.
	 */
	sk.max_type = C.BTRFS_ROOT_BACKREF_KEY
	sk.min_type = C.BTRFS_ROOT_ITEM_KEY

	sk.min_objectid = C.BTRFS_FIRST_FREE_OBJECTID

	/*
	 * set all the other params to the max, we'll take any objectid
	 * and any trans
	 */
	sk.max_objectid = C.BTRFS_LAST_FREE_OBJECTID & (1<<64 - 1)
	sk.max_offset = math.MaxUint64
	sk.max_transid = math.MaxUint64

	fmt.Printf("SK: %#v\n", sk)

	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 fmt.Errorf("Failed to perform the search %v", errno.Error())
		}

		if sk.nr_items == 0 {
			break
		}

		var off uintptr = 0
		for i := uint32(0); i < uint32(sk.nr_items); i++ {

			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

			if sh._type == C.BTRFS_ROOT_BACKREF_KEY {
				ref = (*C.struct_btrfs_root_ref)(addptr(unsafe.Pointer(&args.buf), off))
				goref, err := NewBtrfsRootRef(ref)
				if err != nil {
					return err
				}

				dirId = goref.DirId
				name := C.GoStringN((*C.char)(addptr(unsafe.Pointer(ref), C.sizeof_struct_btrfs_root_ref)), C.int(goref.NameLen))

				ssr := SubvolSearchResult{
					Id:       sh.objectid,
					Gen:      0,
					CGen:     0,
					Parent:   sh.offset,
					TopLevel: sh.offset, /* use ref_id? */

					/* empty */
					/*
						OTime
						UUID
						ParentUUID
						ReceivedUUID
					*/

					/*
						Path: TBD
					*/
				}

				fmt.Printf("objId: %v, offs: %v, dirId: %v, name: %v, nameLen: %v\n", sh.objectid, sh.offset, dirId, name, goref.NameLen)

			} else if sh._type == C.BTRFS_ROOT_ITEM_KEY {
				ri = (*C.struct_btrfs_root_item)(addptr(unsafe.Pointer(&args.buf), off))
				gori, err := NewBtrfsRootItem(ri)
				if err != nil {
					return err
				}

				//fmt.Printf("RI: %#v\n", gori)
				gen = gori.Generation
				flags = gori.Flags

				if sh.len > C.sizeof_struct_btrfs_root_item_v0 {

					t = gori.OTime.Sec
					ogen = gori.OTransId
					ouuid = gori.UUID
					puuid = gori.ParentUUID
					ruuid = gori.ReceivedUUID
				} else {
					ouuid = emptyUUID
					puuid = emptyUUID
					ruuid = emptyUUID
				}

				fmt.Printf("objId: %v, offs: %v, flags: %X, ogen: %v, gen: %v, time: %v, uuid: %s, puuid: %s, ruuid: %s\n",
					sh.objectid, sh.offset, flags, ogen, gen, t, ouuid, puuid, ruuid)
			}

			off += uintptr(sh.len)
			/*
			 * record the mins in sk so we can make sure the
			 * next search doesn't repeat this root
			 */
			sk.min_objectid = sh.objectid
			sk.min_type = sh._type
			sk.min_offset = sh.offset

		}

		sk.nr_items = 4096
		sk.min_offset++
		if sk.min_offset == 0 {
			sk.min_type++
		} else {
			continue
		}

		if sk.min_type > C.BTRFS_ROOT_BACKREF_KEY {
			sk.min_type = C.BTRFS_ROOT_ITEM_KEY
			sk.min_objectid++
		} else {
			continue
		}

		if sk.min_objectid > sk.max_objectid {
			break
		}
	}

	return nil
}
Exemple #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
}