summaryrefslogtreecommitdiffstats
path: root/daemon/ext2.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/ext2.c')
-rw-r--r--daemon/ext2.c194
1 files changed, 193 insertions, 1 deletions
diff --git a/daemon/ext2.c b/daemon/ext2.c
index 99d45743..68247523 100644
--- a/daemon/ext2.c
+++ b/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;
+}