--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "vserver.h"
+#include "vserver-internal.h"
+#include "ext2fs.h"
+
+#include <sys/ioctl.h>
+
+#ifndef EXT2_IMMUTABLE_FILE_FL
+# define EXT2_IMMUTABLE_FILE_FL 0x00000010
+#endif
+
+#ifndef EXT2_IMMUTABLE_LINK_FL
+# define EXT2_IMMUTABLE_LINK_FL 0x00008000
+#endif
+
+int
+vc_X_get_ext2flags(int fd, long *flags)
+{
+ int rc;
+ *flags = 0;
+ rc = ioctl(fd, EXT2_IOC_GETFLAGS, flags);
+ *flags = EXT2FLAGS_KERNEL2USER(*flags);
+
+ return rc;
+}
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "vserver.h"
+#include "vserver-internal.h"
+#include "ext2fs.h"
+
+#include <sys/ioctl.h>
+
+xid_t
+vc_X_get_filecontext(int fd)
+{
+ int c;
+ int rc = ioctl(fd, EXT2_IOC_GETCONTEXT, &c);
+
+ if (rc==-1) return VC_NOCTX;
+ else return c;
+}
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "vserver.h"
+#include "vserver-internal.h"
+#include "ext2fs.h"
+
+#include <sys/ioctl.h>
+
+#ifndef EXT2_IMMUTABLE_FILE_FL
+# define EXT2_IMMUTABLE_FILE_FL 0x00000010
+#endif
+
+#ifndef EXT2_IMMUTABLE_LINK_FL
+# define EXT2_IMMUTABLE_LINK_FL 0x00008000
+#endif
+
+int
+vc_X_set_ext2flags(int fd, long set_flags, long del_flags)
+{
+ long old_flags = 0;
+
+ set_flags = EXT2FLAGS_USER2KERNEL(set_flags);
+ del_flags = EXT2FLAGS_USER2KERNEL(del_flags);
+
+ if (del_flags!=-1) {
+ if (ioctl(fd, EXT2_IOC_GETFLAGS, &old_flags)==-1) return -1;
+ old_flags &= ~del_flags;
+ }
+
+ old_flags |= set_flags;
+ return ioctl(fd, EXT2_IOC_SETFLAGS, &old_flags);
+}
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "vserver.h"
+#include "vserver-internal.h"
+#include "ext2fs.h"
+
+#include <sys/ioctl.h>
+
+int
+vc_X_set_filecontext(int fd, xid_t ctx)
+{
+ int c = ctx;
+ int rc = ioctl(fd, EXT2_IOC_SETCONTEXT, &c);
+
+ return rc;
+}
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "fstool.h"
+#include "util.h"
+
+#include "lib/vserver.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+struct option const
+CMDLINE_OPTIONS[] = {
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { 0,0,0,0 }
+};
+
+char const CMDLINE_OPTIONS_SHORT[] = "Rc:";
+
+void
+showHelp(int fd, char const *cmd, int res)
+{
+ WRITE_MSG(fd, "Usage: ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " -c <ctx|vserver> [-R] [--] <file>+\n\n"
+ " Options:\n"
+ " -R ... recurse through directories\n"
+ " -c ... assign the given context/vserver to the file(s)\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+ exit(res);
+}
+
+void
+showVersion()
+{
+ WRITE_MSG(1,
+ "chxid " VERSION " -- assigns a context to a file\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2004 Enrico Scholz\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
+}
+
+static bool
+setFile(char const *name, char const * display_name, struct stat const *exp_st)
+{
+ bool res = false;
+ int fd = open(name, O_RDONLY);
+
+ if (fd==-1) {
+ perror("open()");
+ return false;
+ }
+
+ if (!exp_st ||
+ !checkForRace(fd, name, exp_st))
+ goto err;
+
+ if (vc_X_set_filecontext(fd, global_args->ctx)==-1) {
+ //perror("vc_X_set_filecontext()");
+ perror(display_name);
+ goto err;
+ }
+
+ res = true;
+
+ err:
+ close(fd);
+ return res;
+}
+
+bool
+handleFile(char const *name, char const * display_name,
+ struct stat const *exp_st)
+{
+ if (S_ISLNK(exp_st->st_mode)) return true;
+
+ return setFile(name, display_name, exp_st);
+}
+
+void
+checkParams(struct Arguments const UNUSED *args, int argc)
+{
+ if (optind==argc) {
+ WRITE_MSG(2, "No filename given; use '--help' for more information\n");
+ exit(1);
+ }
+
+ if (args->ctx==VC_NOCTX) {
+ WRITE_MSG(2, "No valid context given; use '--help' for more information\n");
+ exit(1);
+ }
+}
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "fstool.h"
+#include "util.h"
+#include "wrappers.h"
+#include "wrappers-dirent.h"
+
+#include <lib/vserver.h>
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+struct Arguments const * global_args = 0;
+
+int wrapper_exit_code = 1;
+
+bool
+checkForRace(int fd, char const * name, struct stat const *exp_st)
+{
+ struct stat st;
+
+ if (fstat(fd, &st)==-1) {
+ perror("fstat()");
+ return false;
+ }
+
+ if (st.st_dev != exp_st->st_dev ||
+ st.st_ino != exp_st->st_ino ||
+ st.st_mode != exp_st->st_mode) {
+ close(fd);
+ WRITE_MSG(2, "race while visiting '");
+ WRITE_STR(2, name);
+ WRITE_MSG(2, "'\n");
+ exit(2);
+ }
+
+ return true;
+}
+
+inline static bool
+isSpecialDir(char const *d)
+{
+ return (d[0]=='.' && (d[1]=='\0' || (d[1]=='.' && d[2]=='\0')));
+}
+
+#define CONCAT_PATHS(LHS, LHS_LEN, RHS) \
+ size_t l_rhs = strlen(RHS); \
+ char new_path[(LHS_LEN) + l_rhs + sizeof("/")]; \
+ memcpy(new_path, LHS, (LHS_LEN)); \
+ memcpy(new_path+(LHS_LEN), "/", 1); \
+ memcpy(new_path+(LHS_LEN)+1, RHS, l_rhs); \
+ new_path[(LHS_LEN)+1+l_rhs] = '\0';
+
+static uint64_t
+iterateFilesystem(char const *path)
+{
+ bool do_again = false;
+ size_t path_len = strlen(path);
+ DIR * dir = Eopendir(".");
+ uint64_t err = 0;
+
+ {
+ struct stat st;
+ if (lstat(".", &st)==-1) perror("lstat()");
+ else err += handleFile(".", path, &st) ? 0 : 1;
+ }
+
+ for (;;) {
+ struct dirent *ent = Ereaddir(dir);
+ struct stat st;
+
+ if (ent==0) break;
+ if (isSpecialDir(ent->d_name)) continue;
+
+ if (lstat(ent->d_name, &st)==-1) {
+ perror("lstat()");
+ ++err;
+ continue;
+ }
+
+ if (S_ISDIR(st.st_mode) && global_args->do_recurse) {
+ do_again = true;
+ continue;
+ }
+
+ {
+ CONCAT_PATHS(path, path_len, ent->d_name);
+ err += handleFile(ent->d_name, new_path, &st) ? 0 : 1;
+ }
+ }
+
+ if (do_again) {
+ int cur_dir = Eopen(".", O_RDONLY, 0);
+ rewinddir(dir);
+
+ for (;;) {
+ struct dirent *ent = Ereaddir(dir);
+ struct stat st;
+
+ if (ent==0) break;
+ if (isSpecialDir(ent->d_name)) continue;
+
+ if (lstat(ent->d_name, &st)==-1) {
+ perror("lstat()");
+ ++err;
+ continue;
+ }
+
+ if (!S_ISDIR(st.st_mode)) continue;
+ safeChdir(ent->d_name, &st);
+ {
+ CONCAT_PATHS(path, path_len, ent->d_name);
+ err += iterateFilesystem(new_path);
+ }
+ Efchdir(cur_dir);
+ }
+ Eclose(cur_dir);
+ }
+
+ Eclosedir(dir);
+
+ return err;
+}
+#undef CONCAT_PATHS
+
+static uint64_t
+processFile(char const *path)
+{
+ struct stat st;
+
+ if (lstat(path, &st)==-1) {
+ perror("lstat()");
+ return 1;
+ }
+
+ if (S_ISDIR(st.st_mode) && !global_args->do_display_dir)
+ return iterateFilesystem(path);
+ else
+ return handleFile(path, path, &st);
+}
+
+static xid_t
+resolveCtx(char const *str)
+{
+ xid_t res;
+
+ if (*str==':') ++str;
+ else {
+ char *end_ptr;
+ long result = strtol(str, &end_ptr, 0);
+
+ if (end_ptr>str && *end_ptr==0) return result;
+ }
+
+ res = vc_getVserverCtx(str, vcCFG_AUTO, true, 0);
+ if (res==VC_NOCTX) {
+ WRITE_MSG(2, "Can not find a vserver with name '");
+ WRITE_STR(2, str);
+ WRITE_MSG(2, "', or vserver does not have a static context\n");
+ exit(1);
+ }
+
+ return res;
+}
+
+int main(int argc, char *argv[])
+{
+ uint64_t err_cnt = 0;
+ int i;
+ struct Arguments args = {
+ .do_recurse = false,
+ .do_display_dot = false,
+ .do_display_dir = false,
+ .do_mapping = true,
+ .immutable = false,
+ .immulink = false,
+ .ctx = VC_NOCTX,
+ .is_legacy = false,
+ .do_set = false,
+ .do_unset = false,
+ };
+
+ global_args = &args;
+ while (1) {
+ int c = getopt_long(argc, argv, CMDLINE_OPTIONS_SHORT,
+ CMDLINE_OPTIONS, 0);
+ if (c==-1) break;
+
+ switch (c) {
+ case CMD_HELP : showHelp(1, argv[0], 0);
+ case CMD_VERSION : showVersion();
+ case CMD_IMMUTABLE : args.immutable = true; break;
+ case CMD_IMMULINK : args.immulink = true; break;
+ case CMD_LEGACY : args.is_legacy = true; break;
+ case 'R' : args.do_recurse = true; break;
+ case 'a' : args.do_display_dot = true; break;
+ case 'd' : args.do_display_dir = true; break;
+ case 'n' : args.do_mapping = false; break;
+ case 's' : args.do_set = true; break;
+ case 'u' : args.do_unset = true; break;
+ case 'c' : args.ctx = resolveCtx(optarg); break;
+ default :
+ WRITE_MSG(2, "Try '");
+ WRITE_STR(2, argv[0]);
+ WRITE_MSG(2, " --help\" for more information.\n");
+ return EXIT_FAILURE;
+ break;
+ }
+ }
+
+ checkParams(&args, argc);
+
+ if (optind==argc)
+ err_cnt = processFile(".");
+ else for (i=optind; i<argc; ++i)
+ err_cnt += processFile(argv[i]);
+
+ return err_cnt>0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifndef H_UTIL_VSERVER_SRC_FSTOOL_H
+#define H_UTIL_VSERVER_SRC_FSTOOL_H
+
+#include <getopt.h>
+#include <stdbool.h>
+
+#define CMD_HELP 0x8000
+#define CMD_VERSION 0x8001
+#define CMD_IMMUTABLE 0x8002
+#define CMD_IMMULINK 0x8003
+#define CMD_LEGACY 0x8004
+
+struct stat;
+
+struct Arguments {
+ bool do_recurse;
+ bool do_display_dot;
+ bool do_display_dir;
+ bool do_mapping;
+ bool immutable;
+ bool immulink;
+ xid_t ctx;
+ bool is_legacy;
+ bool do_set;
+ bool do_unset;
+};
+
+extern struct option const CMDLINE_OPTIONS[];
+extern char const CMDLINE_OPTIONS_SHORT[];
+extern struct Arguments const * global_args;
+
+bool checkForRace(int fd, char const * name, struct stat const *exp_st);
+void checkParams(struct Arguments const *, int argc);
+bool handleFile(char const *d_name, char const *full_name, struct stat const *);
+void showHelp(int fd, char const *cmd, int res);
+void showVersion();
+
+#endif // H_UTIL_VSERVER_SRC_FSTOOL_H
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "fstool.h"
+#include "util.h"
+
+#include <lib/vserver.h>
+#include <lib/vserver-internal.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+struct option const
+CMDLINE_OPTIONS[] = {
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { 0,0,0,0 }
+};
+
+char const CMDLINE_OPTIONS_SHORT[] = "Radn";
+
+void
+showHelp(int fd, char const *cmd, int res)
+{
+ WRITE_MSG(fd, "Usage: ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " [-Radn] [--] <file>*\n\n"
+ " Options:\n"
+ " -R ... recurse through directories\n"
+ " -a ... display files starting with '.' also\n"
+ " -d ... list directories like other files instead of\n"
+ " listing their content\n"
+ " -n ... do not try to do xid -> vserver-name mapping\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+ exit(res);
+}
+
+void
+showVersion()
+{
+ WRITE_MSG(1,
+ "lsxid " VERSION " -- shows the context which is associated to a file\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2004 Enrico Scholz\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
+}
+
+void
+checkParams(struct Arguments const UNUSED * args, int UNUSED argc)
+{
+}
+
+static xid_t
+getFileContext(char const *name, struct stat const *exp_st)
+{
+ int fd = open(name, O_RDONLY);
+ xid_t res;
+
+ if (fd==-1) {
+ perror("open()");
+ return VC_NOCTX;
+ }
+
+ if (exp_st)
+ checkForRace(fd, name, exp_st);
+
+ res = vc_X_get_filecontext(fd);
+ if (res==VC_NOCTX)
+ perror("vc_X_get_filecontext()");
+
+ close(fd);
+
+ return res;
+}
+
+bool
+handleFile(char const *name, char const *display_name,
+ struct stat const *exp_st)
+{
+ xid_t ctx = 0;
+ char buf[MAX(sizeof(ctx)*3+1, 20)];
+ bool need_write = true;
+
+ memset(buf, ' ', sizeof buf);
+
+ if (S_ISLNK(exp_st->st_mode)) {
+ memcpy(buf, "-------", 7);
+ write(1, buf, sizeof buf);
+ need_write = false;
+ }
+ else {
+ ctx = getFileContext(name, exp_st);
+
+ if (ctx==VC_NOCTX) {
+ memcpy(buf, "!!ERR!!", 7);
+ write(1, buf, sizeof buf);
+ need_write = false;
+ }
+ else if (global_args->do_mapping) {
+ char const * vname = vc_getVserverByCtx(ctx, 0,0);
+ if (!vname) buf[0] = '\0';
+ else {
+ size_t l = strlen(vname);
+ if (l<sizeof(buf)) write(1, buf, sizeof(buf)-l);
+ write(1, vname, l);
+
+ free((char *)vname);
+ need_write = false;
+ }
+ }
+ }
+
+ if (need_write) {
+ size_t l = utilvserver_fmt_ulong(buf, ctx);
+ if (l<sizeof(buf)) write(1, buf+l, sizeof(buf)-l);
+ write(1, buf, l);
+ }
+
+ write(1, " ", 2);
+ write(1, display_name, strlen(display_name));
+ write(1, "\n", 1);
+
+ return ctx!=VC_NOCTX;
+}
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// 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; version 2 of the License.
+//
+// This program is distributed in the hope that it will 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 to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "fstool.h"
+#include "util.h"
+
+#include <lib/fmt.h>
+#include <lib/vserver.h>
+#include <lib/vserver-internal.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+struct option const
+CMDLINE_OPTIONS[] = {
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { "immutable", no_argument, 0, CMD_IMMUTABLE },
+ { "immulink", no_argument, 0, CMD_IMMULINK },
+ { 0,0,0,0 }
+};
+
+char const CMDLINE_OPTIONS_SHORT[] = "Rsu";
+
+static long set_mask = 0;
+static long del_mask = VC_IMMUTABLE_ALL;
+
+void
+showHelp(int fd, char const *cmd, int res)
+{
+ WRITE_MSG(fd, "Usage: ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " [-Rsu] [--immutable] [--immulink] [--] <file>+\n\n"
+ " Options:\n"
+ " -R ... recurse through directories\n"
+ " -s ... set flag only; when only one of the '--immu*' options\n"
+ " is given, do not delete the other ones\n"
+ " -u ... revert operation and unset the given flags\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+ exit(res);
+}
+
+void
+showVersion()
+{
+ WRITE_MSG(1,
+ "setattr " VERSION " -- sets vserver specific file attributes\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2004 Enrico Scholz\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
+}
+
+void
+checkParams(struct Arguments const * args, int argc)
+{
+ if (optind==argc) {
+ WRITE_MSG(2, "No filename given; use '--help' for more information\n");
+ exit(1);
+ }
+
+ set_mask = 0;
+ if (args->immutable) set_mask |= VC_IMMUTABLE_FILE_FL;
+ if (args->immulink) set_mask |= VC_IMMUTABLE_LINK_FL;
+
+ if (args->do_set) del_mask = 0;
+ else del_mask = VC_IMMUTABLE_ALL;
+
+ if (args->do_unset) {
+ del_mask = set_mask;
+ set_mask = 0;
+ }
+}
+
+static bool
+setFlags(char const *name, char const *display_name,
+ struct stat const *exp_st)
+{
+ int fd = open(name, O_RDONLY);
+ int res = false;
+
+ if (fd==-1) {
+ perror("open()");
+ return false;
+ }
+
+ if (!exp_st ||
+ !checkForRace(fd, name, exp_st))
+ goto err;
+
+ if (vc_X_set_ext2flags(fd, set_mask, del_mask)==-1) {
+ perror(display_name);
+ goto err;
+ }
+
+ res = true;
+
+ err:
+ close(fd);
+ return res;
+}
+
+bool
+handleFile(char const *name, char const * display_name,
+ struct stat const *exp_st)
+{
+ if (S_ISLNK(exp_st->st_mode)) return true;
+
+ return setFlags(name, display_name, exp_st);
+}