| /* |
| * Copyright (c) 2005 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| * |
| * 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 the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it would be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include "libxfs.h" |
| #include "command.h" |
| #include "attrset.h" |
| #include "io.h" |
| #include "output.h" |
| #include "type.h" |
| #include "init.h" |
| #include "fprint.h" |
| #include "faddr.h" |
| #include "field.h" |
| #include "inode.h" |
| #include "malloc.h" |
| |
| static int attr_set_f(int argc, char **argv); |
| static int attr_remove_f(int argc, char **argv); |
| static void attrset_help(void); |
| |
| static const cmdinfo_t attr_set_cmd = |
| { "attr_set", "aset", attr_set_f, 1, -1, 0, |
| N_("[-r|-s|-p|-u] [-n] [-R|-C] [-v n] name"), |
| N_("set the named attribute on the current inode"), attrset_help }; |
| static const cmdinfo_t attr_remove_cmd = |
| { "attr_remove", "aremove", attr_remove_f, 1, -1, 0, |
| N_("[-r|-s|-p|-u] [-n] name"), |
| N_("remove the named attribute from the current inode"), attrset_help }; |
| |
| static void |
| attrset_help(void) |
| { |
| dbprintf(_( |
| "\n" |
| " The 'attr_set' and 'attr_remove' commands provide interfaces for debugging\n" |
| " the extended attribute allocation and removal code.\n" |
| " Both commands require an attribute name to be specified, and the attr_set\n" |
| " command allows an optional value length (-v) to be provided as well.\n" |
| " There are 4 namespace flags:\n" |
| " -r -- 'root'\n" |
| " -u -- 'user' (default)\n" |
| " -s -- 'secure'\n" |
| "\n" |
| " For attr_set, these options further define the type of set operation:\n" |
| " -C -- 'create' - create attribute, fail if it already exists\n" |
| " -R -- 'replace' - replace attribute, fail if it does not exist\n" |
| " The backward compatibility mode 'noattr2' can be emulated (-n) also.\n" |
| "\n")); |
| } |
| |
| void |
| attrset_init(void) |
| { |
| if (!expert_mode) |
| return; |
| |
| add_command(&attr_set_cmd); |
| add_command(&attr_remove_cmd); |
| } |
| |
| static int |
| attr_set_f( |
| int argc, |
| char **argv) |
| { |
| xfs_inode_t *ip = NULL; |
| char *name, *value, *sp; |
| int c, valuelen = 0, flags = 0; |
| |
| if (cur_typ == NULL) { |
| dbprintf(_("no current type\n")); |
| return 0; |
| } |
| if (cur_typ->typnm != TYP_INODE) { |
| dbprintf(_("current type is not inode\n")); |
| return 0; |
| } |
| |
| while ((c = getopt(argc, argv, "rusCRnv:")) != EOF) { |
| switch (c) { |
| /* namespaces */ |
| case 'r': |
| flags |= LIBXFS_ATTR_ROOT; |
| flags &= ~LIBXFS_ATTR_SECURE; |
| break; |
| case 'u': |
| flags &= ~(LIBXFS_ATTR_ROOT | LIBXFS_ATTR_SECURE); |
| break; |
| case 's': |
| flags |= LIBXFS_ATTR_SECURE; |
| flags &= ~LIBXFS_ATTR_ROOT; |
| break; |
| |
| /* modifiers */ |
| case 'C': |
| flags |= LIBXFS_ATTR_CREATE; |
| break; |
| case 'R': |
| flags |= LIBXFS_ATTR_REPLACE; |
| break; |
| |
| case 'n': |
| mp->m_flags |= LIBXFS_MOUNT_COMPAT_ATTR; |
| break; |
| |
| /* value length */ |
| case 'v': |
| valuelen = (int)strtol(optarg, &sp, 0); |
| if (*sp != '\0' || valuelen < 0 || valuelen > 64*1024) { |
| dbprintf(_("bad attr_set valuelen %s\n"), optarg); |
| return 0; |
| } |
| break; |
| |
| default: |
| dbprintf(_("bad option for attr_set command\n")); |
| return 0; |
| } |
| } |
| |
| if (optind != argc - 1) { |
| dbprintf(_("too few options for attr_set (no name given)\n")); |
| return 0; |
| } |
| |
| name = argv[optind]; |
| |
| if (valuelen) { |
| value = (char *)memalign(getpagesize(), valuelen); |
| if (!value) { |
| dbprintf(_("cannot allocate buffer (%d)\n"), valuelen); |
| goto out; |
| } |
| memset(value, 'v', valuelen); |
| } else { |
| value = NULL; |
| } |
| |
| if (libxfs_iget(mp, NULL, iocur_top->ino, 0, &ip, 0)) { |
| dbprintf(_("failed to iget inode %llu\n"), |
| (unsigned long long)iocur_top->ino); |
| goto out; |
| } |
| |
| if (libxfs_attr_set(ip, (unsigned char *)name, |
| (unsigned char *)value, valuelen, flags)) { |
| dbprintf(_("failed to set attr %s on inode %llu\n"), |
| name, (unsigned long long)iocur_top->ino); |
| goto out; |
| } |
| |
| /* refresh with updated inode contents */ |
| set_cur_inode(iocur_top->ino); |
| |
| out: |
| mp->m_flags &= ~LIBXFS_MOUNT_COMPAT_ATTR; |
| if (ip) |
| IRELE(ip); |
| if (value) |
| free(value); |
| return 0; |
| } |
| |
| static int |
| attr_remove_f( |
| int argc, |
| char **argv) |
| { |
| xfs_inode_t *ip = NULL; |
| char *name; |
| int c, flags = 0; |
| |
| if (cur_typ == NULL) { |
| dbprintf(_("no current type\n")); |
| return 0; |
| } |
| if (cur_typ->typnm != TYP_INODE) { |
| dbprintf(_("current type is not inode\n")); |
| return 0; |
| } |
| |
| while ((c = getopt(argc, argv, "rusn")) != EOF) { |
| switch (c) { |
| /* namespaces */ |
| case 'r': |
| flags |= LIBXFS_ATTR_ROOT; |
| flags &= ~LIBXFS_ATTR_SECURE; |
| break; |
| case 'u': |
| flags &= ~(LIBXFS_ATTR_ROOT | LIBXFS_ATTR_SECURE); |
| break; |
| case 's': |
| flags |= LIBXFS_ATTR_SECURE; |
| flags &= ~LIBXFS_ATTR_ROOT; |
| break; |
| |
| case 'n': |
| mp->m_flags |= LIBXFS_MOUNT_COMPAT_ATTR; |
| break; |
| |
| default: |
| dbprintf(_("bad option for attr_remove command\n")); |
| return 0; |
| } |
| } |
| |
| if (optind != argc - 1) { |
| dbprintf(_("too few options for attr_remove (no name given)\n")); |
| return 0; |
| } |
| |
| name = argv[optind]; |
| |
| if (libxfs_iget(mp, NULL, iocur_top->ino, 0, &ip, 0)) { |
| dbprintf(_("failed to iget inode %llu\n"), |
| (unsigned long long)iocur_top->ino); |
| goto out; |
| } |
| |
| if (libxfs_attr_remove(ip, (unsigned char *)name, flags)) { |
| dbprintf(_("failed to remove attr %s from inode %llu\n"), |
| name, (unsigned long long)iocur_top->ino); |
| goto out; |
| } |
| |
| /* refresh with updated inode contents */ |
| set_cur_inode(iocur_top->ino); |
| |
| out: |
| mp->m_flags &= ~LIBXFS_MOUNT_COMPAT_ATTR; |
| if (ip) |
| IRELE(ip); |
| return 0; |
| } |