Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 117 lines (107 sloc) 3.035 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
/*
mairix - message index builder and finder for maildir folders.

**********************************************************************
* Copyright (C) Richard P. Curnow 2005
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
**********************************************************************
*/

#include "mairix.h"
#include <sys/utsname.h>
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>

static char *lock_file_name = NULL;

/* This locking code was originally written for tdl */

void lock_database(char *path, int forced_unlock)/*{{{*/
{
  struct utsname uu;
  struct passwd *pw;
  int pid;
  int len;
  char *tname;
  struct stat sb;
  FILE *out;

  if (uname(&uu) < 0) {
    perror("uname");
    exit(1);
  }
  pw = getpwuid(getuid());
  if (!pw) {
    perror("getpwuid");
    exit(1);
  }
  pid = getpid();
  len = 1 + strlen(path) + 5;
  lock_file_name = new_array(char, len);
  sprintf(lock_file_name, "%s.lock", path);

  if (forced_unlock) {
    unlock_database();
    forced_unlock = 0;
  }

  len += strlen(uu.nodename);
  /* add on max width of pid field (allow up to 32 bit pid_t) + 2 '.' chars */
  len += (10 + 2);
  tname = new_array(char, len);
  sprintf(tname, "%s.%d.%s", lock_file_name, pid, uu.nodename);
  out = fopen(tname, "w");
  if (!out) {
    fprintf(stderr, "Cannot open lock file %s for writing\n", tname);
    exit(1);
  }
  fprintf(out, "%d,%s,%s\n", pid, uu.nodename, pw->pw_name);
  fclose(out);

  if (link(tname, lock_file_name) < 0) {
    /* check if link count==2 */
    if (stat(tname, &sb) < 0) {
      fprintf(stderr, "Could not stat the lock file\n");
      unlink(tname);
      exit(1);
    } else {
      if (sb.st_nlink != 2) {
        FILE *in;
        in = fopen(lock_file_name, "r");
        if (in) {
          char line[2048];
          fgets(line, sizeof(line), in);
          line[strlen(line)-1] = 0; /* strip trailing newline */
          fprintf(stderr, "Database %s appears to be locked by (pid,node,user)=(%s)\n", path, line);
          unlink(tname);
          exit(1);
        }
      } else {
        /* lock succeeded apparently */
      }
    }
  } else {
    /* lock succeeded apparently */
  }
  unlink(tname);
  free(tname);
  return;
}
/*}}}*/
void unlock_database(void)/*{{{*/
{
  if (lock_file_name) unlink(lock_file_name);
  return;
}
/*}}}*/
void unlock_and_exit(int code)/*{{{*/
{
  unlock_database();
  exit(code);
}
/*}}}*/
Something went wrong with that request. Please try again.