libbtrfsutil: add get and set filesystem label
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
9f48d1b72f
commit
3d5c0c203c
|
@ -50,3 +50,11 @@ LIBBTRFSUTIL_1.2 {
|
|||
global:
|
||||
btrfs_util_delete_subvolume_by_id_fd;
|
||||
} LIBBTRFSUTIL_1.1;
|
||||
|
||||
LIBBTRFSUTIL_1.3 {
|
||||
global:
|
||||
btrfs_util_filesystem_get_label;
|
||||
btrfs_util_filesystem_get_label_fd;
|
||||
btrfs_util_filesystem_set_label;
|
||||
btrfs_util_filesystem_set_label_fd;
|
||||
} LIBBTRFSUTIL_1.2;
|
||||
|
|
|
@ -67,6 +67,8 @@ enum btrfs_util_error {
|
|||
BTRFS_UTIL_ERROR_GET_SUBVOL_ROOTREF_FAILED,
|
||||
BTRFS_UTIL_ERROR_INO_LOOKUP_USER_FAILED,
|
||||
BTRFS_UTIL_ERROR_FS_INFO_FAILED,
|
||||
BTRFS_UTIL_ERROR_GET_LABEL_FAILED,
|
||||
BTRFS_UTIL_ERROR_SET_LABEL_FAILED,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -122,6 +124,39 @@ enum btrfs_util_error btrfs_util_wait_sync(const char *path, uint64_t transid);
|
|||
*/
|
||||
enum btrfs_util_error btrfs_util_wait_sync_fd(int fd, uint64_t transid);
|
||||
|
||||
#define BTRFS_UTIL_LABEL_SIZE 256
|
||||
|
||||
/**
|
||||
* btrfs_util_filesystem_set_label() - Set label of the filesystem under path
|
||||
* @path: Path on a Btrfs filesystem.
|
||||
* @label: New label as string, maximum length must be less than %BTRFS_LABEL_SIZE.
|
||||
*
|
||||
* Return: %BTRFS_UTIL_OK on success, non-zero error code on failure.
|
||||
*/
|
||||
enum btrfs_util_error btrfs_util_filesystem_set_label(const char *path,
|
||||
const char *label);
|
||||
|
||||
/**
|
||||
* btrfs_util_filesystem_get_label_fd() - See btrfs_util_filesystem_get_label().
|
||||
*/
|
||||
enum btrfs_util_error btrfs_util_filesystem_set_label_fd(int fd,
|
||||
const char *label);
|
||||
|
||||
/**
|
||||
* btrfs_util_filesystem_get_label - Get labelf of the filesystem under path
|
||||
* @path: Path on a Btrfs filesystem.
|
||||
* @label: Buffer where to store the label, must be at least %BTRFS_LABEL_SIZE.
|
||||
*
|
||||
* Return: %BTRFS_UTIL_OK on success, non-zero error code on failure.
|
||||
*/
|
||||
enum btrfs_util_error btrfs_util_filesystem_get_label(const char *path,
|
||||
char *label);
|
||||
|
||||
/**
|
||||
* btrfs_util_filesystem_get_label_fd() - See btrfs_util_filesystem_get_label().
|
||||
*/
|
||||
enum btrfs_util_error btrfs_util_filesystem_get_label_fd(int fd,
|
||||
char *label);
|
||||
/**
|
||||
* btrfs_util_is_subvolume() - Return whether a given path is a Btrfs subvolume.
|
||||
* @path: Path to check.
|
||||
|
|
|
@ -53,6 +53,10 @@ static const char * const error_messages[] = {
|
|||
"Could not resolve subvolume path with BTRFS_IOC_INO_LOOKUP_USER",
|
||||
[BTRFS_UTIL_ERROR_FS_INFO_FAILED] =
|
||||
"Could not get filesystem information",
|
||||
[BTRFS_UTIL_ERROR_GET_LABEL_FAILED] =
|
||||
"Could not get filesystem label",
|
||||
[BTRFS_UTIL_ERROR_SET_LABEL_FAILED] =
|
||||
"Could not set filesystem label",
|
||||
};
|
||||
|
||||
PUBLIC const char *btrfs_util_strerror(enum btrfs_util_error err)
|
||||
|
|
|
@ -100,3 +100,66 @@ PUBLIC enum btrfs_util_error btrfs_util_wait_sync_fd(int fd, uint64_t transid)
|
|||
|
||||
return BTRFS_UTIL_OK;
|
||||
}
|
||||
|
||||
PUBLIC enum btrfs_util_error btrfs_util_filesystem_set_label_fd(int fd,
|
||||
const char *label)
|
||||
{
|
||||
int ret;
|
||||
char buf[BTRFS_UTIL_LABEL_SIZE];
|
||||
|
||||
if (strlen(label) >= BTRFS_UTIL_LABEL_SIZE) {
|
||||
errno = EINVAL;
|
||||
return BTRFS_UTIL_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strncpy(buf, label, BTRFS_UTIL_LABEL_SIZE - 1);
|
||||
|
||||
ret = ioctl(fd, BTRFS_IOC_SET_FSLABEL, buf);
|
||||
if (ret == -1)
|
||||
return BTRFS_UTIL_ERROR_GET_LABEL_FAILED;
|
||||
|
||||
return BTRFS_UTIL_OK;
|
||||
}
|
||||
|
||||
PUBLIC enum btrfs_util_error btrfs_util_filesystem_set_label(const char *path,
|
||||
const char *label)
|
||||
{
|
||||
enum btrfs_util_error err;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return BTRFS_UTIL_ERROR_OPEN_FAILED;
|
||||
|
||||
err = btrfs_util_filesystem_set_label_fd(fd, label);
|
||||
SAVE_ERRNO_AND_CLOSE(fd);
|
||||
return err;
|
||||
}
|
||||
|
||||
PUBLIC enum btrfs_util_error btrfs_util_filesystem_get_label_fd(int fd,
|
||||
char *label)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Kernel does not return more than BTRFS_LABEL_SIZE/BTRFS_UTIL_LABEL_SIZE */
|
||||
ret = ioctl(fd, BTRFS_IOC_GET_FSLABEL, label);
|
||||
if (ret == -1)
|
||||
return BTRFS_UTIL_ERROR_GET_LABEL_FAILED;
|
||||
|
||||
return BTRFS_UTIL_OK;
|
||||
}
|
||||
|
||||
PUBLIC enum btrfs_util_error btrfs_util_filesystem_get_label(const char *path,
|
||||
char *label)
|
||||
{
|
||||
enum btrfs_util_error err;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return BTRFS_UTIL_ERROR_OPEN_FAILED;
|
||||
|
||||
err = btrfs_util_filesystem_get_label_fd(fd, label);
|
||||
SAVE_ERRNO_AND_CLOSE(fd);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ void SetFromBtrfsUtilErrorWithPaths(enum btrfs_util_error err,
|
|||
PyObject *filesystem_sync(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
PyObject *start_sync(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
PyObject *wait_sync(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
PyObject *filesystem_get_label(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
PyObject *fielsystem_set_label(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
PyObject *is_subvolume(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
PyObject *subvolume_id(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
PyObject *subvolume_path(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
|
|
|
@ -92,3 +92,53 @@ PyObject *wait_sync(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
path_cleanup(&path);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject *filesystem_get_label(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *keywords[] = {"path", NULL};
|
||||
struct path_arg path = {.allow_fd = true};
|
||||
enum btrfs_util_error err;
|
||||
char label[BTRFS_UTIL_LABEL_SIZE];
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:filesystem_get_label",
|
||||
keywords, &path_converter, &path))
|
||||
return NULL;
|
||||
|
||||
if (path.path)
|
||||
err = btrfs_util_filesystem_get_label(path.path, label);
|
||||
else
|
||||
err = btrfs_util_filesystem_get_label_fd(path.fd, label);
|
||||
if (err) {
|
||||
SetFromBtrfsUtilErrorWithPath(err, &path);
|
||||
path_cleanup(&path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_cleanup(&path);
|
||||
return PyUnicode_DecodeFSDefault(label);
|
||||
}
|
||||
|
||||
PyObject *filesystem_set_label(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *keywords[] = {"path", "label", NULL};
|
||||
struct path_arg path = {.allow_fd = true};
|
||||
enum btrfs_util_error err;
|
||||
char *label;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&s:filesystem_set_label",
|
||||
keywords, &path_converter, &path, &label))
|
||||
return NULL;
|
||||
|
||||
if (path.path)
|
||||
err = btrfs_util_filesystem_set_label(path.path, label);
|
||||
else
|
||||
err = btrfs_util_filesystem_set_label_fd(path.fd, label);
|
||||
if (err) {
|
||||
SetFromBtrfsUtilErrorWithPath(err, &path);
|
||||
path_cleanup(&path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_cleanup(&path);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
|
|
@ -176,6 +176,12 @@ static PyMethodDef btrfsutil_methods[] = {
|
|||
"path -- string, bytes, path-like object, or open file descriptor\n"
|
||||
"transid -- int transaction ID to wait for, or zero for the current\n"
|
||||
"transaction"},
|
||||
{"filesystem_get_label", (PyCFunction)filesystem_get_label,
|
||||
METH_VARARGS | METH_KEYWORDS,
|
||||
"filesystem_get_label(path) -> str\n\n"
|
||||
"Get filesystem label.\n\n"
|
||||
"Arguments:\n"
|
||||
"path -- string, bytes, path-like object, or open file descriptor"},
|
||||
{"is_subvolume", (PyCFunction)is_subvolume,
|
||||
METH_VARARGS | METH_KEYWORDS,
|
||||
"is_subvolume(path) -> bool\n\n"
|
||||
|
|
|
@ -76,7 +76,7 @@ class BtrfsTestCase(unittest.TestCase):
|
|||
else:
|
||||
mkfs = 'mkfs.btrfs'
|
||||
try:
|
||||
subprocess.check_call([mkfs, '-q', image])
|
||||
subprocess.check_call([mkfs, '-q', '-L', 'BTRFS-PROGS-PYTEST', image])
|
||||
subprocess.check_call(['mount', '-o', 'loop', '--', image, mountpoint])
|
||||
except Exception as e:
|
||||
os.rmdir(mountpoint)
|
||||
|
|
|
@ -71,3 +71,9 @@ class TestSubvolume(BtrfsTestCase):
|
|||
new_generation = self.super_generation()
|
||||
self.assertGreater(new_generation, old_generation)
|
||||
old_generation = new_generation
|
||||
|
||||
def test_filesystem_get_label(self):
|
||||
for arg in self.path_or_fd(self.mountpoint):
|
||||
with self.subTest(type=type(arg)):
|
||||
label = btrfsutil.filesystem_get_label(arg)
|
||||
self.assertEqual(label, 'BTRFS-PROGS-PYTEST')
|
||||
|
|
Loading…
Reference in New Issue