Logo Search packages:      
Sourcecode: unionfs-tools version File versions  Download package

unionctl.c

/*
 * Copyright (c) 2003-2006 Erez Zadok
 * Copyright (c) 2003-2006 Charles P. Wright
 * Copyright (c) 2005-2006 Josef Sipek
 * Copyright (c) 2005      Arun M. Krishnakumar
 * Copyright (c) 2005-2006 David P. Quigley
 * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
 * Copyright (c) 2003      Puja Gupta
 * Copyright (c) 2003      Harikesavan Krishnan
 * Copyright (c) 2003-2006 Stony Brook University
 * Copyright (c) 2003-2006 The Research Foundation of State University of New York
 *
 * For specific licensing information, see the COPYING file distributed with
 * this package.
 *
 * This Copyright notice must be kept intact and distributed with all sources.
 */
/*
 *  $Id: unionctl.c,v 1.10 2007/04/30 19:50:04 ezk Exp $
 */


#include <stdio.h>
#include <stdlib.h>
#include "unionctl.h"

static const char *progname;

void __attribute__ ((__noreturn__)) __usage(int line);

#define usage() __usage(__LINE__)

void __attribute__ ((__noreturn__)) __usage(int line)
{
#ifdef DEBUG
      fprintf(stderr, "Line: %d\n", line);
#endif
      fprintf(stderr,
            "unionctl version: $Id: unionctl.c,v 1.10 2007/04/30 19:50:04 ezk Exp $\n");
      fprintf(stderr, "Distributed with Unionfs " PACKAGE_VERSION "\n");
      fprintf(stderr, "\n");
      fprintf(stderr, "unionctl UNION ACTION [arguments]\n");
      fprintf(stderr,
            "ACTION can be --add, --remove, --mode, --list, or --query.\nFurther arguments depend on ACTION.\n");
      fprintf(stderr,
            "\tunionctl UNION --add [ --before BRANCH | --after BRANCH ] [ --mode (rw|ro|nfsro) ] DIRECTORY\n");
      fprintf(stderr, "\tunionctl UNION --remove BRANCH\n");
      fprintf(stderr, "\tunionctl UNION --mode BRANCH (rw|ro|nfsro)\n");
      fprintf(stderr, "\tunionctl UNION --list\n");
      fprintf(stderr, "\tunionctl FILENAME --query\n");
      fprintf(stderr,
            "The unionctl man page has a more detailed description of its usage.\n");
      exit(EXIT_FAILURE);
}

#define ADD 1
#define REMOVE 2
#define MODE 3
#define LIST 4
#define     QUERY 5

int main(int argc, char *argv[])
{
      struct unionfs_branch *branches;
      int ret, i;

      char *path, resolv_path[PATH_MAX];
      int action;

      char *branchpath;
      int branchnum;
      int unionpos = 1;
      int modepos = 2;
      int perms;
      int rwb_branch;

      progname = argv[0];

      /* check that minimum number of args were specified */
      if (argc < 3)
            usage();

      if (argv[1][0] == '-' && argv[1][1] == '-') {
            modepos = 1;
            unionpos = 2;
      } else {
            modepos = 2;
            unionpos = 1;
      }

      if (realpath(argv[unionpos], resolv_path) == NULL) {
            perror(argv[unionpos]);
            exit(EXIT_FAILURE);
      }
      path = resolv_path;
      if (strcmp(path, "/") && (path[strlen(path) - 1] == '/')) {
            path[strlen(path) - 1] = '\0';
      }

      if (!strcmp(argv[modepos], "--add")) {
            action = ADD;
      } else if (!strcmp(argv[modepos], "--remove")) {
            action = REMOVE;
      } else if (!strcmp(argv[modepos], "--mode")) {
            action = MODE;
      } else if (!strcmp(argv[modepos], "--list")) {
            action = LIST;
      } else if (!strcmp(argv[modepos], "--query")) {
            action = QUERY;
      } else {
            usage();
      }


      /* Parse the action's options into something usable, and do it. */
      switch (action) {
      case ADD:
            if (argc < 4)
                  usage();

            /* Default values if the user leaves them unspecified. */
            branchnum = -1;
            perms = MAY_READ | MAY_WRITE;
            branchpath = NULL;
            for (i = 3; i < argc; i++) {
                  if (argv[i][0] == '-' && argv[i][1] == '-') {
                        if (!strcmp(argv[i], "--before")) {
                              i++;
                              if (i == argc) {
                                    fprintf(stderr,
                                          "%s requires an argument!\n",
                                          argv[i - 1]);
                                    usage();
                              }

                              branchnum = unionfs_get_branch(path, argv[i]);
                              if (branchnum == -1) {
                                    fprintf(stderr,
                                          "%s is not a valid branch.\nThe current branch configuration is:\n",
                                          argv[i]);
                                    unionfs_dump(path, "\t");
                                    exit(EXIT_FAILURE);
                              }
                        } else if (!strcmp(argv[i], "--after")) {
                              i++;
                              if (i == argc) {
                                    fprintf(stderr,
                                          "%s requires an argument!\n",
                                          argv[i - 1]);
                                    usage();
                              }

                              branchnum = unionfs_get_branch(path, argv[i]);
                              if (branchnum == -1) {
                                    fprintf(stderr,
                                          "%s is not a valid branch.\nThe current branch configuration is:\n",
                                          argv[i]);
                                    unionfs_dump(path, "\t");
                                    exit(EXIT_FAILURE);
                              }
                              branchnum++;
                        } else if (!strcmp(argv[i], "--mode")) {
                              i++;
                              if (i == argc) {
                                    fprintf(stderr,
                                          "%s requires an argument!\n",
                                          argv[i - 1]);
                                    usage();
                              }

                              perms = parse_rw(argv[i]);
                              if (!perms) {
                                    fprintf(stderr,
                                          "Valid modes are ro, nfsro and rw you specified: \"%s\"\n",
                                          argv[i]);
                                    usage();
                              }
                        } else {
                              fprintf(stderr, "Unknown option: %s\n",
                                    argv[i]);
                              usage();
                        }
                  } else {
                        int branchchk = -1;
                        /* The options must go before the path */
                        if ((i + 1) != argc) {
                              fprintf(stderr,
                                    "The path of the branch to add must go after all options.\n");
                              usage();
                        }
                        branchchk = unionfs_get_branch(path, argv[i]);
                        if (branchchk != -1) {
                              fprintf(stderr,
                                    "%s already exists in the Union.\n",
                                    argv[i]);
                              usage();
                        }
                        if (branchnum == -1)
                              branchnum = 0;
                        branchpath = argv[i];
                  }
            }
            if (!branchpath) {
                  fprintf(stderr,
                        "You must specify the path to add into the union!\n");
                  usage();
            }

            errno = 0;
            ret = unionfs_add(argv[unionpos], branchpath, branchnum, perms);
            if (ret < 0) {
                  switch (errno) {
                  case E2BIG:
                        fprintf(stderr,
                              "Unionfs supports only %d branches.\n",
                              FD_SETSIZE);
                        break;
                  }
                  fprintf(stderr, "Failed to add %s into %s: %s\n",
                        branchpath, path, strerror(errno));
                  exit(EXIT_FAILURE);
            }
            break;
      case MODE:
            if (argc != 5) {
                  usage();
            }

            branchnum = 3;
            perms = parse_rw(argv[4]);
            if (!perms) {
                  branchnum = 4;
                  perms = parse_rw(argv[3]);
                  if (!perms) {
                        usage();
                        exit(EXIT_FAILURE);
                  }
            }

            branchpath = argv[branchnum];

            /* Set a branches writeable status. */
            rwb_branch = unionfs_get_branch(argv[unionpos], branchpath);
            if (rwb_branch == -1) {
                  fprintf(stderr,
                        "%s is not a valid branch.\nThe current branch configuration is:\n",
                        branchpath);
                  unionfs_dump(path, "\t");
                  exit(EXIT_FAILURE);
            }

            ret = unionfs_mode(argv[unionpos], rwb_branch, perms);
            if (ret < 0) {
                  fprintf(stderr,
                        "Failed to set permissions for %s in %s: %s\n",
                        branchpath, path, strerror(errno));
                  exit(EXIT_FAILURE);
            }

            goto out;
            break;
      case REMOVE:
            if (argc != 4)
                  usage();

            branchpath = argv[3];

            branchnum = unionfs_get_branch(argv[unionpos], branchpath);
            if (branchnum == -1) {
                  fprintf(stderr,
                        "%s is not a valid branch.\nThe current branch configuration is:\n",
                        branchpath);
                  unionfs_dump(path, "\t");
                  exit(EXIT_FAILURE);
            }

            ret = unionfs_remove(argv[unionpos], branchnum);
            if (ret < 0) {
                  fprintf(stderr, "Failed to remove %s from %s: %s\n",
                        branchpath, path, strerror(errno));
                  exit(EXIT_FAILURE);
            }
            break;
      case LIST:
            unionfs_dump(argv[unionpos], "\t");
            break;

      case QUERY:
            if (argc != 3) {
                  usage();
            }

            ret = unionfs_query(argv[unionpos], &branches);
            if ( ret < 0 ) {
                  fprintf(stderr, "Unable to retrieve list of branches for %s: %s\n",
                              argv[unionpos], strerror(errno));
                  exit(EXIT_FAILURE);
            }
            else {
                  for ( i = 0; i < ret; i++ ) {
                        char r, w, n;
                        r = (branches[i].perms & MAY_READ) ? 'r' : '-';
                        w = (branches[i].perms & MAY_WRITE) ? 'w' : '-';
                        n = (branches[i].perms & MAY_NFSRO) ? 'n' : '-';
                        printf("%s\t%s (%c%c%c)\n", argv[unionpos],
                                    branches[i].path, r, w, n);
                  }
            }
            break;
      }

      out:
      exit(EXIT_SUCCESS);
}

/*
 *
 * vim:shiftwidth=8
 * vim:tabstop=8
 *
 * For Emacs:
 * Local variables:
 * c-basic-offset: 8
 * c-comment-only-line-offset: 0
 * c-offsets-alist: ((statement-block-intro . +) (knr-argdecl-intro . 0)
 *              (substatement-open . 0) (label . 0) (statement-cont . +))
 * indent-tabs-mode: t
 * tab-width: 8
 * End:
 */

Generated by  Doxygen 1.6.0   Back to index