mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
New APIs for reading and writing ext2 file attributes and file generation.
The new APIs are: get-e2attrs: List ext2 file attributes of a file. set-e2attrs: Set or clear ext2 file attributes of a file. get-e2generation: Get ext2 file generation of a file. set-e2generation: Set ext2 file generation of a file. These are implemented using the lsattr and chattr programs from e2fsprogs.
This commit is contained in:
194
daemon/ext2.c
194
daemon/ext2.c
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -694,3 +694,195 @@ do_tune2fs (const char *device, /* only required parameter */
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_chars (const void *vc1, const void *vc2)
|
||||
{
|
||||
char c1 = * (char *) vc1;
|
||||
char c2 = * (char *) vc2;
|
||||
return c1 - c2;
|
||||
}
|
||||
|
||||
char *
|
||||
do_get_e2attrs (const char *filename)
|
||||
{
|
||||
int r;
|
||||
char *buf;
|
||||
char *out, *err;
|
||||
size_t i, j;
|
||||
|
||||
buf = sysroot_path (filename);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = command (&out, &err, "lsattr", "-d", "--", buf, NULL);
|
||||
free (buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", "lsattr", filename, err);
|
||||
free (err);
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
free (err);
|
||||
|
||||
/* Output looks like:
|
||||
* -------------e- filename
|
||||
* Remove the dashes and return everything up to the space.
|
||||
*/
|
||||
for (i = j = 0; out[j] != ' '; j++) {
|
||||
if (out[j] != '-')
|
||||
out[i++] = out[j];
|
||||
}
|
||||
|
||||
out[i] = '\0';
|
||||
|
||||
/* Sort the output, mainly to make testing simpler. */
|
||||
qsort (out, i, sizeof (char), compare_chars);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_set_e2attrs (const char *filename, const char *attrs, int clear)
|
||||
{
|
||||
int r;
|
||||
char *buf;
|
||||
char *err;
|
||||
size_t i, j;
|
||||
int lowers[26], uppers[26];
|
||||
char attr_arg[26*2+1+1]; /* '+'/'-' + attrs + trailing '\0' */
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_SET_E2ATTRS_CLEAR_BITMASK))
|
||||
attr_arg[0] = '+';
|
||||
else if (!clear)
|
||||
attr_arg[0] = '+';
|
||||
else
|
||||
attr_arg[0] = '-';
|
||||
j = 1;
|
||||
|
||||
/* You can't write "chattr - file", so we have to just return if
|
||||
* the string is empty.
|
||||
*/
|
||||
if (STREQ (attrs, ""))
|
||||
return 0;
|
||||
|
||||
/* Valid attrs are all lower or upper case ASCII letters. Check
|
||||
* this and that there are no duplicates.
|
||||
*/
|
||||
memset (lowers, 0, sizeof lowers);
|
||||
memset (uppers, 0, sizeof uppers);
|
||||
for (; *attrs; attrs++) {
|
||||
/* These are reserved by the chattr program for command line flags. */
|
||||
if (*attrs == 'R' || *attrs == 'V' || *attrs == 'f' || *attrs == 'v') {
|
||||
reply_with_error ("bad file attribute '%c'", *attrs);
|
||||
return -1;
|
||||
}
|
||||
else if (*attrs >= 'a' && *attrs <= 'z') {
|
||||
i = *attrs - 'a';
|
||||
if (lowers[i] > 0)
|
||||
goto error_duplicate;
|
||||
lowers[i]++;
|
||||
attr_arg[j++] = *attrs;
|
||||
}
|
||||
else if (*attrs >= 'A' && *attrs <= 'Z') {
|
||||
i = *attrs - 'A';
|
||||
if (uppers[i] > 0) {
|
||||
error_duplicate:
|
||||
reply_with_error ("duplicate file attribute '%c'", *attrs);
|
||||
return -1;
|
||||
}
|
||||
uppers[i]++;
|
||||
attr_arg[j++] = *attrs;
|
||||
}
|
||||
else {
|
||||
reply_with_error ("unknown file attribute '%c'", *attrs);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
attr_arg[j] = '\0';
|
||||
|
||||
buf = sysroot_path (filename);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = command (NULL, &err, "chattr", attr_arg, "--", buf, NULL);
|
||||
free (buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", "chattr", filename, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t
|
||||
do_get_e2generation (const char *filename)
|
||||
{
|
||||
int r;
|
||||
char *buf;
|
||||
char *out, *err;
|
||||
int64_t ret;
|
||||
|
||||
buf = sysroot_path (filename);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = command (&out, &err, "lsattr", "-dv", "--", buf, NULL);
|
||||
free (buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", "lsattr", filename, err);
|
||||
free (err);
|
||||
free (out);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
if (sscanf (out, "%" SCNu64, &ret) != 1) {
|
||||
reply_with_error ("cannot parse output from '%s' command: %s",
|
||||
"lsattr", out);
|
||||
free (out);
|
||||
return -1;
|
||||
}
|
||||
free (out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
do_set_e2generation (const char *filename, int64_t generation)
|
||||
{
|
||||
int r;
|
||||
char *buf;
|
||||
char *err;
|
||||
char generation_str[64];
|
||||
|
||||
buf = sysroot_path (filename);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf (generation_str, sizeof generation_str,
|
||||
"%" PRIu64, (uint64_t) generation);
|
||||
|
||||
r = command (NULL, &err, "chattr", "-v", generation_str, "--", buf, NULL);
|
||||
free (buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", "chattr", filename, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user