Beispiel #1
0
/*}}}*/
void write_database(struct database *db, char *filename, int do_integrity_checks)/*{{{*/
{
  int file_len;
  int fd;
  char *data, *cdata;
  unsigned int *uidata;
  struct write_map map;

  if (do_integrity_checks) {
    check_database_integrity(db);
  }

  if (!verify_mbox_size_constraints(db)) {
    unlock_and_exit(1);
  }

  /* Work out mappings */
  compute_mapping(db, &map);

  file_len = char_length(db) + (4 * map.beyond_last_ui_offset);

  create_rw_mapping(filename, file_len, &fd, &data);
  uidata = (unsigned int *) data; /* align(int) < align(page)! */
  cdata = data + (4 * map.beyond_last_ui_offset);

  write_header(data, uidata, db, &map);
  cdata = write_type_and_flag_table(db, uidata, data, cdata);
  cdata = write_messages(db, &map, uidata, data, cdata);
  cdata = write_mbox_headers(db, &map, uidata, data, cdata);
  cdata = write_mbox_checksums(db, &map, uidata, data, cdata);
  cdata = write_toktable(db->to, &map.to, uidata, data, cdata, "To");
  cdata = write_toktable(db->cc, &map.cc, uidata, data, cdata, "Cc");
  cdata = write_toktable(db->from, &map.from, uidata, data, cdata, "From");
  cdata = write_toktable(db->subject, &map.subject, uidata, data, cdata, "Subject");
  cdata = write_toktable(db->body, &map.body, uidata, data, cdata, "Body");
  cdata = write_toktable(db->attachment_name, &map.attachment_name, uidata, data, cdata, "Attachment Name");
  cdata = write_toktable2(db->msg_ids, &map.msg_ids, uidata, data, cdata, "(Threading)");

  /* Write data */
  /* Unmap / close file */
  if (munmap(data, file_len) < 0) {
    report_error("munmap", filename);
    unlock_and_exit(2);
  }
  if (fsync(fd) < 0) {
    report_error("fsync", filename);
    unlock_and_exit(2);
  }
  if (close(fd) < 0) {
    report_error("close", filename);
    unlock_and_exit(2);
  }
}
Beispiel #2
0
Datei: main.c Projekt: jwise/tdl
static char *get_database_path(int traverse_up)/*{{{*/
{
  char *env_var;
  env_var = getenv("TDL_DATABASE");
  if (env_var) {
    return env_var;
  } else {
    int at_root, orig_size, size, dbname_len, found, stat_result;
    char *orig_cwd, *cwd, *result, *filename;
    struct stat statbuf;
    
    dbname_len = strlen(DBNAME);
    size = 16;
    orig_size = 16;
    found = 0;
    at_root = 0;
    cwd = new_array(char, size);
    orig_cwd = new_array(char, orig_size);
    do {
      result = getcwd(orig_cwd, orig_size);
      if (!result) {
        if (errno == ERANGE) {
          orig_size <<= 1;
          orig_cwd = grow_array(char, orig_size, orig_cwd);
        } else {
          fprintf(stderr, "Unexpected error reading current directory\n");
          unlock_and_exit(1);
        }
      }
    } while (!result);
Beispiel #3
0
/*}}}*/
void close_db(struct read_db *x)/*{{{*/
{
  free_toktable_db(&x->to);
  free_toktable_db(&x->cc);
  free_toktable_db(&x->from);
  free_toktable_db(&x->subject);
  free_toktable_db(&x->body);
  free_toktable_db(&x->attachment_name);
  free_toktable2_db(&x->msg_ids);

  if (munmap(x->data, x->len) < 0) {
    perror("munmap");
    unlock_and_exit(2);
  }
  free(x);
  return;
}
Beispiel #4
0
static void create_rw_mapping(char *filename, size_t len, int *out_fd, char **out_data)/*{{{*/
{
  int fd;
  char *data;
  struct stat sb;

  fd = open(filename, O_RDWR | O_CREAT, 0600);
  if (fd < 0) {
    report_error("open", filename);
    unlock_and_exit(2);
  }

  if (fstat(fd, &sb) < 0) {
    report_error("stat", filename);
    unlock_and_exit(2);
  }

  if (sb.st_size < len) {
    /* Extend */
    if (lseek(fd, len - 1, SEEK_SET) < 0) {
      report_error("lseek", filename);
      unlock_and_exit(2);
    }
    if (write(fd, "\000", 1) < 0) {
      report_error("write", filename);
      unlock_and_exit(2);
    }
  } else if (sb.st_size > len) {
    /* Truncate */
    if (ftruncate(fd, len) < 0) {
      report_error("ftruncate", filename);
      unlock_and_exit(2);
    }
  } else {
    /* Exactly the right length already - nothing to do! */
  }

  data = mmap(0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  if (data == MAP_FAILED) {
    report_error("writer:mmap", filename);
    unlock_and_exit(2);
  }

  *out_data = data;
  *out_fd = fd;
}
Beispiel #5
0
/*}}}*/
struct read_db *open_db(char *filename)/*{{{*/
{
  int fd, len;
  char *data;
  struct stat sb;
  struct read_db *result;
  unsigned int *uidata;
  unsigned char *ucdata;

  fd = open(filename, O_RDONLY);
  if (fd < 0) {
    report_error("open", filename);
    unlock_and_exit (2);
  }

  if (fstat(fd, &sb) < 0) {
    report_error("stat", filename);
    unlock_and_exit(2);
  }

  len = sb.st_size;

  data = (char *) mmap(0, len, PROT_READ, MAP_SHARED, fd, 0);
  if (data == MAP_FAILED) {
    report_error("reader:mmap", filename);
    unlock_and_exit(2);
  }

  if (!data) {
    /* Empty file opened => database corrupt for sure */
    if (close(fd) < 0) {
      report_error("close", filename);
      unlock_and_exit(2);
    }
    return NULL;
  }

  if (close(fd) < 0) {
    report_error("close", filename);
    unlock_and_exit(2);
  }

  result = new(struct read_db);
  uidata = (unsigned int *) data; /* alignment is assured */
  ucdata = (unsigned char *) data;
  result->len = len;
  result->data = data;

  /*{{{ Magic number check */
  if (ucdata[0] == HEADER_MAGIC0 ||
      ucdata[1] == HEADER_MAGIC1 ||
      ucdata[2] == HEADER_MAGIC2) {
    if (ucdata[3] != HEADER_MAGIC3) {
      fprintf(stderr, "Another version of this program produced the existing database!  Please rebuild.\n");
      unlock_and_exit(2);
    }
  } else {
    fprintf(stderr, "The existing database wasn't produced by this program!  Please rebuild.\n");
    unlock_and_exit(2);
  }
  /*}}}*/
  /* {{{ Endianness check */
  if (uidata[UI_ENDIAN] == 0x11223344) {
    fprintf(stderr, "The endianness of the database is reversed for this machine\n");
    unlock_and_exit(2);
  } else if (uidata[UI_ENDIAN] != 0x44332211) {
    fprintf(stderr, "The endianness of this machine is strange (or database is corrupt)\n");
    unlock_and_exit(2);
  }
  /* }}} */

  /* Now build tables of where things are in the file */
  result->n_msgs = uidata[UI_N_MSGS];
  result->msg_type_and_flags = ucdata + uidata[UI_MSG_TYPE_AND_FLAGS];
  result->path_offsets = uidata + uidata[UI_MSG_CDATA];
  result->mtime_table = uidata + uidata[UI_MSG_MTIME];
  result->size_table = uidata + uidata[UI_MSG_SIZE];
  result->date_table = uidata + uidata[UI_MSG_DATE];
  result->tid_table  = uidata + uidata[UI_MSG_TID];

  result->n_mboxen            = uidata[UI_MBOX_N];
  result->mbox_paths_table    = uidata + uidata[UI_MBOX_PATHS];
  result->mbox_entries_table  = uidata + uidata[UI_MBOX_ENTRIES];
  result->mbox_mtime_table    = uidata + uidata[UI_MBOX_MTIME];
  result->mbox_size_table     = uidata + uidata[UI_MBOX_SIZE];
  result->mbox_checksum_table = uidata + uidata[UI_MBOX_CKSUM];

  result->hash_key = uidata[UI_HASH_KEY];

  read_toktable_db(data, &result->to, UI_TO_BASE, uidata);
  read_toktable_db(data, &result->cc, UI_CC_BASE, uidata);
  read_toktable_db(data, &result->from, UI_FROM_BASE, uidata);
  read_toktable_db(data, &result->subject, UI_SUBJECT_BASE, uidata);
  read_toktable_db(data, &result->body, UI_BODY_BASE, uidata);
  read_toktable_db(data, &result->attachment_name, UI_ATTACHMENT_NAME_BASE, uidata);
  read_toktable2_db(data, &result->msg_ids, UI_MSGID_BASE, uidata);

  return result;
}