File: dotlock.c

package info (click to toggle)
mairix 0.23+git20131125-0.3
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,296 kB
  • ctags: 1,299
  • sloc: ansic: 11,345; sh: 1,000; yacc: 185; makefile: 135; lex: 87; perl: 34
file content (116 lines) | stat: -rw-r--r-- 3,035 bytes parent folder | download | duplicates (4)
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);
}
/*}}}*/