return ret;
}
-int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
- u64 max_block_count, int discard)
+int btrfs_prepare_device(int fd, const char *file, int zero_end,
+ u64 *block_count_ret, u64 max_block_count, int discard)
{
u64 block_count;
struct stat st;
}
/*
- * __strncpy__null - strncpy with null termination
+ * __strncpy_null - strncpy with null termination
* @dest: the target array
* @src: the source string
* @n: maximum bytes to copy (size of *dest)
* byte ('\0'), to the buffer pointed to by dest, up to a maximum
* of n bytes. Then ensure that dest is null-terminated.
*/
-char *__strncpy__null(char *dest, const char *src, size_t n)
+char *__strncpy_null(char *dest, const char *src, size_t n)
{
strncpy(dest, src, n);
if (n > 0)
* 0 for nothing found
* -1 for internal error
*/
-static int
-check_overwrite(
- char *device)
+static int check_overwrite(const char *device)
{
const char *type;
blkid_probe pr = NULL;
if (dev_cnt > 1 &&
((metadata_profile | data_profile) & BTRFS_BLOCK_GROUP_DUP)) {
- fprintf(stderr,
- "ERROR: DUP is not allowed when FS has multiple devices\n");
- return 1;
+ warning("DUP is not recommended on filesystem with multiple devices");
}
if (metadata_profile & ~allowed) {
fprintf(stderr,
* 1: something is wrong, an error is printed
* 0: all is fine
*/
-int test_dev_for_mkfs(char *file, int force_overwrite)
+int test_dev_for_mkfs(const char *file, int force_overwrite)
{
int ret, fd;
struct stat st;
return 0;
}
-int is_vol_small(char *file)
+int is_vol_small(const char *file)
{
int fd = -1;
int e;
* first whitespace delimited token is a case insensitive match with yes
* or y.
*/
-int ask_user(char *question)
+int ask_user(const char *question)
{
char buf[30] = {0,};
char *saveptr = NULL;
return 1;
}
-char* btrfs_group_type_str(u64 flag)
+const char* btrfs_group_type_str(u64 flag)
{
u64 mask = BTRFS_BLOCK_GROUP_TYPE_MASK |
BTRFS_SPACE_INFO_GLOBAL_RSV;
}
}
-char* btrfs_group_profile_str(u64 flag)
+const char* btrfs_group_profile_str(u64 flag)
{
switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
case 0:
}
}
-u64 disk_size(char *path)
+u64 disk_size(const char *path)
{
struct statfs sfs;
return sfs.f_bsize * sfs.f_blocks;
}
-u64 get_partition_size(char *dev)
+u64 get_partition_size(const char *dev)
{
u64 result;
int fd = open(dev, O_RDONLY);
if (len >= PATH_MAX || len >= destlen)
return -ENAMETOOLONG;
- __strncpy__null(dest, src, destlen);
+ __strncpy_null(dest, src, destlen);
return 0;
}
return (int)stfs.f_type == BTRFS_SUPER_MAGIC;
}
-char *get_subvol_name(char *mnt, char *full_path)
+const char *subvol_strip_mountpoint(const char *mnt, const char *full_path)
{
int len = strlen(mnt);
if (!len)
return full_path + len;
}
+
+/*
+ * Returns
+ * <0: Std error
+ * 0: All fine
+ * 1: Error; and error info printed to the terminal. Fixme.
+ * 2: If the fullpath is root tree instead of subvol tree
+ */
+int get_subvol_info(const char *fullpath, struct root_info *get_ri)
+{
+ u64 sv_id;
+ int ret = 1;
+ int fd = -1;
+ int mntfd = -1;
+ char *mnt = NULL;
+ const char *svpath = NULL;
+ DIR *dirstream1 = NULL;
+ DIR *dirstream2 = NULL;
+
+ ret = test_issubvolume(fullpath);
+ if (ret < 0)
+ return ret;
+ if (!ret) {
+ error("not a subvolume: %s", fullpath);
+ return 1;
+ }
+
+ ret = find_mount_root(fullpath, &mnt);
+ if (ret < 0)
+ return ret;
+ if (ret > 0) {
+ error("%s doesn't belong to btrfs mount point", fullpath);
+ return 1;
+ }
+ ret = 1;
+ svpath = subvol_strip_mountpoint(mnt, fullpath);
+
+ fd = btrfs_open_dir(fullpath, &dirstream1, 1);
+ if (fd < 0)
+ goto out;
+
+ ret = btrfs_list_get_path_rootid(fd, &sv_id);
+ if (ret) {
+ error("can't get rootid for '%s'", fullpath);
+ goto out;
+ }
+
+ mntfd = btrfs_open_dir(mnt, &dirstream2, 1);
+ if (mntfd < 0)
+ goto out;
+
+ if (sv_id == BTRFS_FS_TREE_OBJECTID) {
+ ret = 2;
+ /*
+ * So that caller may decide if thats an error or just fine.
+ */
+ goto out;
+ }
+
+ memset(get_ri, 0, sizeof(*get_ri));
+ get_ri->root_id = sv_id;
+
+ ret = btrfs_get_subvol(mntfd, get_ri);
+ if (ret)
+ error("can't find '%s': %d", svpath, ret);
+
+out:
+ close_file_or_dir(mntfd, dirstream2);
+ close_file_or_dir(mntfd, dirstream1);
+ free(mnt);
+
+ return ret;
+}