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

imap.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.
 */

#include "unionfs.h"
#include "unionimap.h"

#if defined HAVE_LIBUUID && defined HAVE_UUID_UUID_H


extern int mkfsid(char *path, fsid_t * fsid);

/**
 * create_forwardmap(char *filename)
 * verifies that the forward map is valid.
 *
 */
int unionfs_create_forwardmap(char *filename)
{
      int byteswritten = 0, err = 0;
      int fwrdmap = 0;
      struct fmaphdr header;
      void *table = NULL;
      uuid_t uuid;
      fwrdmap = creat(filename, S_IRUSR | S_IWUSR);
      if (fwrdmap < 0) {
            errno = EINVAL;
            err = -1;
            goto out;
      }
      memset(&header, 0, sizeof(struct fmaphdr));
      header.version = FORWARDMAP_VERSION;
      header.magic = FORWARDMAP_MAGIC;
      header.usedbranches = 0;
      uuid_generate(uuid);
      memcpy(&header.uuid, &uuid, UUID_LEN);
      byteswritten = write(fwrdmap, &header, sizeof(struct fmaphdr));
      if ( byteswritten < sizeof(struct fmaphdr)) {
            perror("Failed Writting header: ");
            errno = EIO;
            err = -1;
            goto out;
      }
      table = malloc(sizeof(struct bmapent) * MAX_MAPS);
      if (!table) {
            errno = ENOMEM;
            err = -1;
            goto out;
      }
      memset(table, 0, sizeof(struct bmapent) * MAX_MAPS);
      byteswritten = write(fwrdmap, table, sizeof(struct bmapent) * MAX_MAPS);
      if (byteswritten < sizeof(struct bmapent) * MAX_MAPS) {
            perror("Failed writting table: ");
            errno = EIO;
            err = -1;
            goto out;
      }
out:
      if (fwrdmap)
            close(fwrdmap);
      if (table)
            free(table);
      return err;
}
int unionfs_open_forwardmap(struct fmaphdr *header, char *forwardmap)
{
      int fwrdmap = 0, bytesread = 0, err = 0;
      fwrdmap = open(forwardmap, O_RDWR);
      if (fwrdmap < 0) {
            perror("Open on Forwardmap  Failed: ");
            goto out_error;
      }
      bytesread = read(fwrdmap, header, sizeof(struct fmaphdr));
      if (bytesread < 0 || bytesread < sizeof(struct fmaphdr)) {
            errno = EINVAL;
            goto out_error;
      }
      if (header->magic != FORWARDMAP_MAGIC
                  || header->version != FORWARDMAP_VERSION) {
            errno = EINVAL;
            goto out_error;
      }
      if (header->usedbranches == MAX_MAPS -1) {
            fprintf(stderr,
                        "Forwardmap already contains maximum number of reverse maps");
            errno = EINVAL;
            goto out_error;
      }
      err = fwrdmap;
      goto out;
out_error:
      err = -1;
      if (fwrdmap)
            close(fwrdmap);
out:
      return err;
}
int unionfs_check_if_entry_exists(int fwrdmap, struct statfs stat, char *path)
{
      int err = 0, bytesread = 0, i;
      struct fmaphdr header;
      struct bmapent btable[MAX_MAPS];
      fsid_t fsid;

      if (fwrdmap < 0) {
            errno = EINVAL;
            err = -1;
            goto out;
      }
      err = lseek(fwrdmap, 0L, SEEK_SET);
      if (err)
            goto out;

      bytesread = read(fwrdmap, &header, sizeof(struct fmaphdr));
      if (bytesread != sizeof(struct fmaphdr)) {
            errno = EIO;
            err = -1;
            goto out;
      }
      bytesread =
            read(fwrdmap, &btable, sizeof(struct bmapent) * MAX_MAPS);
      if (bytesread != sizeof(struct bmapent) * MAX_MAPS) {
            errno = EIO;
            err = -1;
            goto out;
      }
      if (((unsigned int *)&stat.f_fsid)[0]
                  || ((unsigned int *)&stat.f_fsid)[1]) {
            fsid = stat.f_fsid;
      } else {
            err = mkfsid(path, &fsid);
            if (err)
                  goto out;
      }
      for (i = 0; i < header.usedbranches; i++) {
            if (!memcmp(&fsid, &btable[i].fsid, sizeof(fsid_t))) {
                  err = 1;
                  break;
            }
      }
out:
      return err;
}
int unionfs_create_reversemap(char *filename, char *path, char *forwardmap)
{
      int byteswritten = 0, err = 0, seekres = 0;
      off_t offset = 0;
      int fwrdmap = 0, revmap = 0;
      struct fmaphdr fwdheader;
      struct rmaphdr revheader;
      struct statfs stat;
      struct bmapent ent;
      uuid_t uuid;

      fwrdmap = unionfs_open_forwardmap(&fwdheader, forwardmap);
      if (fwrdmap < 0) {
            err = fwrdmap;
            goto out;
      }
      memset(&stat, 0, sizeof(struct statfs));
      err = statfs(path, &stat);
      if (err) {
            perror("statfs failed on path: ");
            goto out;
      }
      err = unionfs_check_if_entry_exists(fwrdmap, stat, path);
      if (err) {
            if (err > 0) {
                  errno = EINVAL;
                  err = -1;
                  fprintf(stderr,
                              "Specified fs already exists in the forward map\n");
            }
            goto out;
      }
      revmap = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
      if (!revmap) {
            errno = EINVAL;
            err = -1;
            perror("Open on Reversemap failed: ");
            goto out;
      }

      revheader.version = REVERSEMAP_VERSION;
      revheader.magic = REVERSEMAP_MAGIC;
      uuid_generate(uuid);
      memcpy(&revheader.revuuid, &uuid, UUID_LEN);
      memcpy(&revheader.fwduuid, &fwdheader.uuid, UUID_LEN);

      if (((unsigned int *)&stat.f_fsid)[0]
                  || ((unsigned int *)&stat.f_fsid)[1]) {
            revheader.fsid = stat.f_fsid;
      } else {
            err = mkfsid(path, &revheader.fsid);
            if (err)
                  goto out;

      }
      byteswritten = write(revmap, &revheader, sizeof(struct rmaphdr));
      if (byteswritten < sizeof(struct rmaphdr)) {
            errno = EIO;
            err = -1;
            perror("Reversemap Write failed: ");
            goto out;
      }

      offset =
            sizeof(struct fmaphdr) +
            (fwdheader.usedbranches * sizeof(struct bmapent));
      seekres = lseek(fwrdmap, offset, SEEK_SET);
      if (!(seekres == offset)) {
            errno = EIO;
            err = -1;
            perror("Couldn't seek to offset in uuid table: ");
      }
      errno = 0;
      memcpy(&ent.uuid, &uuid, UUID_LEN);
      memcpy(&ent.fsid, &revheader.fsid, sizeof(fsid_t));
      byteswritten = write(fwrdmap, &ent, sizeof(struct bmapent));
      if (byteswritten < sizeof(struct bmapent)) {
            perror("Forwardmap Write failed to write uuid to table: ");
            errno = EIO;
            err = -1;
            goto out;
      }
      fwdheader.usedbranches++;
      offset = (int)&(((struct fmaphdr *)(0))->usedbranches);
      seekres = lseek(fwrdmap, offset, SEEK_SET);
      if (!(seekres == offset)) {
            perror("Couldent seek to usedbranch offset: ");
            errno = EIO;
            err = -1;
            goto out;
      }
      byteswritten = write(fwrdmap, &fwdheader.usedbranches, sizeof(uint8_t));
      if (byteswritten < sizeof(uint8_t)) {
            perror("Forwardmap Write failed to update usedbranches: ");
            errno = EIO;
            err = -1;
            goto out;
      }

out:
      if (fwrdmap) {
            close(fwrdmap);
      }
      if (revmap) {
            close(revmap);
      }
      return err;
}
int unionfs_print_forwardmap(int file, int debug_level)
{
      int err = 0, bytesread = 0, i;
      struct fmaphdr header;
      struct bmapent btable[MAX_MAPS];
      char *uuid_unparsed;
      struct fmapent entry;

      if (file < 0 || debug_level <= 0) {
            errno = EINVAL;
            err = -1;
            goto out;
      }
      err = lseek(file, 0L, SEEK_SET);
      if (err)
            goto out;

      bytesread = read(file, &header, sizeof(struct fmaphdr));
      if (bytesread != sizeof(struct fmaphdr)) {
            errno = EIO;
            err = -1;
            goto out;
      }
      uuid_unparsed = malloc(UUID_UNP_LEN);
      if (!uuid_unparsed) {
            errno = EIO;
            err = -1;
            goto out;
      }
      memset(uuid_unparsed, 0, UUID_UNP_LEN);
      fprintf(stdout, "Unionfs Forwardmap:\n");
      fprintf(stdout, "Magic: %x\n", header.magic);
      fprintf(stdout, "Version: %d\n", header.version);
      fprintf(stdout, "Used Branches: %d\n", header.usedbranches);
      uuid_unparse(header.uuid, uuid_unparsed);
      fprintf(stdout, "UUID: %s\n", uuid_unparsed);
      bytesread = read(file, &btable, sizeof(struct bmapent) * MAX_MAPS);
      if (bytesread != sizeof(struct bmapent) * MAX_MAPS) {
            errno = EIO;
            err = -1;
            goto out;
      }
      for (i = 0; i < header.usedbranches; i++) {
            fprintf(stdout, "Branch at index : %d\n", i);
            fprintf(stdout, "fsid: %04x%04x\n",
                        ((unsigned int *)&btable[i].fsid)[0],
                        ((unsigned int *)&btable[i].fsid)[1]);
            uuid_unparse(btable[i].uuid, uuid_unparsed);
            fprintf(stdout, "uuid: %s\n", uuid_unparsed);
      }
      if (debug_level > 1) {
            unsigned long inode = 1;
            fprintf(stdout, "%-11s %-8s %-22s\n", "Unionfs", "FS Num",
                        "Lower-Level");
            while (read(file, &entry, sizeof(struct fmapent))) {
                  fprintf(stdout, "%-11lu %-8d %-22llu\n", inode++,
                              entry.fsnum,
                              (long long unsigned int)entry.inode);
            }
      }
out:
      return err;

}
int unionfs_print_reversemap(int file, int debug_level)
{

      int err = 0, bytesread = 0;
      struct rmaphdr header;
      char *uuid_unparsed = NULL;
      uint64_t inode;

      if (file < 0 || debug_level <= 0) {
            errno = EINVAL;
            err = -1;
            goto out;
      }
      err = lseek(file, 0L, SEEK_SET);
      if (err)
            goto out;

      bytesread = read(file, &header, sizeof(struct rmaphdr));
      if (bytesread != sizeof(struct rmaphdr)) {
            errno = EIO;
            err = -1;
            goto out;
      }
      uuid_unparsed = malloc(UUID_UNP_LEN);
      if (!uuid_unparsed) {
            errno = ENOMEM;
            err = -1;
            goto out;
      }
      memset(uuid_unparsed, 0, UUID_UNP_LEN);
      fprintf(stdout, "Unionfs Reversemap:\n");
      fprintf(stdout, "Magic: %x\n", header.magic);
      fprintf(stdout, "Version: %d\n", header.version);
      uuid_unparse(header.fwduuid, uuid_unparsed);
      fprintf(stdout, "Forward UUID: %s\n", uuid_unparsed);
      uuid_unparse(header.revuuid, uuid_unparsed);
      fprintf(stdout, "Reverse UUID: %s\n", uuid_unparsed);
      fprintf(stdout, "fsid: %04x%04x\n", ((unsigned int *)&header.fsid)[0],
                  ((unsigned int *)&header.fsid)[1]);
      if (debug_level > 1) {
            fprintf(stdout, "%-11s %-22s\n", "Lower", "Unionfs");
            unsigned long lowerlevel = 0;
            while (read(file, &inode, sizeof(uint64_t))) {
                  if (inode) {
                        fprintf(stdout, "%-11lu %-22llu\n",
                                    lowerlevel++,
                                    (long long unsigned int)inode);
                  }
            }
      }
out:
      free(uuid_unparsed);

      return err;
}
int unionfs_dump_map(char *filename, int debug_level)
{
      int err = 0, bytesread = 0, file = 0;
      uint32_t magic;

      file = open(filename, O_RDONLY);
      if (file < 0) {
            errno = EINVAL;
            err = -1;
            goto out;
      }
      bytesread = read(file, &magic, sizeof(uint32_t));
      if (bytesread < sizeof(uint32_t)) {
            errno = EINVAL;
            err = -1;
            goto out;
      }
      if (magic == FORWARDMAP_MAGIC) {
            err = unionfs_print_forwardmap(file, debug_level);
      } else if (magic == REVERSEMAP_MAGIC) {
            err = unionfs_print_reversemap(file, debug_level);
      } else {
            err = -1;
            errno = EINVAL;
      }
out:
      if (file) {
            close(file);
      }

      return err;
}

#endif /* HAVE_LIBUUID */

Generated by  Doxygen 1.6.0   Back to index