Skip to content

Commit

Permalink
exec/util: add blkid API to query block devices based on FSTYPE
Browse files Browse the repository at this point in the history
This change adds a building block to query block devices based on
the particular filesystem.
  • Loading branch information
sohankunkerkar committed Jul 13, 2021
1 parent fdbd1e4 commit b5cb10a
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 1 deletion.
42 changes: 42 additions & 0 deletions internal/exec/util/blkid.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
static inline void _free_probe(blkid_probe *pr) { if (pr) blkid_free_probe(*pr); }
#define _cleanup_probe_ __attribute__((cleanup(_free_probe)))

static inline void _free_cache(blkid_cache *gcache) { blkid_put_cache(*gcache); }
#define _cleanup_cache_ __attribute__((cleanup(_free_cache)))

static inline void _free_iterator(blkid_dev_iterate *iter) { blkid_dev_iterate_end(*iter); }
#define _cleanup_iterator_ __attribute__((cleanup(_free_iterator)))

static result_t extract_part_info(blkid_partition part, struct partition_info *info, long sector_divisor);

static result_t checked_copy(char *dest, const char *src, size_t len);
Expand Down Expand Up @@ -248,3 +254,39 @@ static result_t extract_part_info(blkid_partition part, struct partition_info *i

return RESULT_OK;
}

// blkid_get_block_devices fetches block devices with the given FSTYPE
result_t blkid_get_block_devices(const char *fstype, struct block_device_list *device) {
blkid_dev_iterate iter _cleanup_iterator_ = NULL;
blkid_dev dev;
blkid_cache cache _cleanup_cache_ = NULL;
int err, count = 0;
const char *ctmp = NULL;

if (blkid_get_cache(&cache, "/dev/null") != 0)
return RESULT_GET_CACHE_FAILED;

if (blkid_probe_all(cache) != 0)
return RESULT_PROBE_FAILED;

iter = blkid_dev_iterate_begin(cache);

blkid_dev_set_search(iter, "TYPE", fstype);

while (blkid_dev_next(iter, &dev) == 0) {
dev = blkid_verify(cache, dev);
if (!dev)
continue;
ctmp = blkid_dev_devname(dev);
if (count > MAX_BLOCK_DEVICES)
return RESULT_MAX_BLOCK_DEVICES;
err = checked_copy(device->path[count], ctmp, MAX_BLOCK_DEVICE_PATH_LEN);
if (err)
return err;
count++;
}
blkid_dev_iterate_end(iter);

device->count = count;
return RESULT_OK;
}
21 changes: 21 additions & 0 deletions internal/exec/util/blkid.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ func cResultToErr(res C.result_t) error {
return errors.New("bad partition index specified")
case C.RESULT_GET_PARTLIST_FAILED:
return errors.New("failed to get list of partitions")
case C.RESULT_GET_CACHE_FAILED:
return fmt.Errorf("failed to retrieve cache")
case C.RESULT_DISK_HAS_NO_TYPE:
return errors.New("disk has no type string, despite having a partition table")
case C.RESULT_DISK_NOT_GPT:
Expand All @@ -118,6 +120,8 @@ func cResultToErr(res C.result_t) error {
return errors.New("bad parameters passed")
case C.RESULT_OVERFLOW:
return errors.New("return value doesn't fit in buffer")
case C.RESULT_MAX_BLOCK_DEVICES:
return fmt.Errorf("found too many filesystems of the specified type")
case C.RESULT_NO_TOPO:
return errors.New("failed to get topology information")
case C.RESULT_NO_SECTOR_SIZE:
Expand Down Expand Up @@ -190,3 +194,20 @@ func filesystemLookup(device string, allowAmbivalent bool, fieldName string) (st
}
return string(buf[:bytes.IndexByte(buf[:], 0)]), nil
}

// GetBlockDevices returns a slice of block devices with the given filesystem
func GetBlockDevices(fstype string) ([]string, error) {
var dev C.struct_block_device_list
res := C.blkid_get_block_devices(C.CString(fstype), &dev)

if res != C.RESULT_OK {
return nil, cResultToErr(res)
}

length := int(dev.count)
blkDeviceList := make([]string, length)
for i := 0; i < length; i++ {
blkDeviceList[i] = C.GoString(&dev.path[i][0])
}
return blkDeviceList, nil
}
13 changes: 12 additions & 1 deletion internal/exec/util/blkid.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ typedef enum {
RESULT_NO_PARTITION_TABLE,
RESULT_BAD_INDEX,
RESULT_GET_PARTLIST_FAILED,
RESULT_GET_CACHE_FAILED,
RESULT_DISK_HAS_NO_TYPE,
RESULT_DISK_NOT_GPT,
RESULT_BAD_PARAMS,
RESULT_OVERFLOW,
RESULT_MAX_BLOCK_DEVICES,
RESULT_NO_TOPO,
RESULT_NO_SECTOR_SIZE,
RESULT_BAD_SECTOR_SIZE,
Expand All @@ -48,6 +50,14 @@ struct partition_info {
int number;
};

#define MAX_BLOCK_DEVICES 10
#define MAX_BLOCK_DEVICE_PATH_LEN 50

struct block_device_list {
char path[MAX_BLOCK_DEVICES][MAX_BLOCK_DEVICE_PATH_LEN];
int count;
};

result_t blkid_lookup(const char *device, bool allow_ambivalent, const char *field_name, char buf[], size_t buf_len);

result_t blkid_get_num_partitions(const char *device, int *ret);
Expand All @@ -57,5 +67,6 @@ result_t blkid_get_logical_sector_size(const char *device, int *ret_sector_size)
// WARNING part_num may not be what you expect. see the .c file's comment for why
result_t blkid_get_partition(const char *device, int part_num, struct partition_info *info);

#endif // _BLKID_H_
result_t blkid_get_block_devices(const char *fstype, struct block_device_list *device);

#endif // _BLKID_H_

0 comments on commit b5cb10a

Please sign in to comment.