Postfix3.3.1
全て データ構造 ファイル 関数 変数 型定義 マクロ定義
myflock.c
[詳解]
1 /*++
2 /* NAME
3 /* myflock 3
4 /* SUMMARY
5 /* lock open file
6 /* SYNOPSIS
7 /* #include <myflock.h>
8 /*
9 /* int myflock(fd, lock_style, operation)
10 /* int fd;
11 /* int lock_style;
12 /* int operation;
13 /* DESCRIPTION
14 /* myflock() locks or unlocks an entire open file.
15 /*
16 /* In the case of a blocking request, a call that fails due to
17 /* foreseeable transient problems is retried once per second.
18 /*
19 /* Arguments:
20 /* .IP fd
21 /* The open file to be locked/unlocked.
22 /* .IP lock_style
23 /* One of the following values:
24 /* .RS
25 /* .IP MYFLOCK_STYLE_FLOCK
26 /* Use BSD-style flock() locking.
27 /* .IP MYFLOCK_STYLE_FCNTL
28 /* Use POSIX-style fcntl() locking.
29 /* .RE
30 /* .IP operation
31 /* One of the following values:
32 /* .RS
33 /* .IP MYFLOCK_OP_NONE
34 /* Release any locks the process has on the specified open file.
35 /* .IP MYFLOCK_OP_SHARED
36 /* Attempt to acquire a shared lock on the specified open file.
37 /* This is appropriate for read-only access.
38 /* .IP MYFLOCK_OP_EXCLUSIVE
39 /* Attempt to acquire an exclusive lock on the specified open
40 /* file. This is appropriate for write access.
41 /* .PP
42 /* In addition, setting the MYFLOCK_OP_NOWAIT bit causes the
43 /* call to return immediately when the requested lock cannot
44 /* be acquired.
45 /* .RE
46 /* DIAGNOSTICS
47 /* myflock() returns 0 in case of success, -1 in case of failure.
48 /* A problem description is returned via the global \fIerrno\fR
49 /* variable. In the case of a non-blocking lock request the value
50 /* EAGAIN means that a lock is claimed by someone else.
51 /*
52 /* Panic: attempts to use an unsupported file locking method or
53 /* to implement an unsupported operation.
54 /* LICENSE
55 /* .ad
56 /* .fi
57 /* The Secure Mailer license must be distributed with this software.
58 /* AUTHOR(S)
59 /* Wietse Venema
60 /* IBM T.J. Watson Research
61 /* P.O. Box 704
62 /* Yorktown Heights, NY 10598, USA
63 /*--*/
64 
65 /* System library. */
66 
67 #include "sys_defs.h"
68 #include <errno.h>
69 #include <unistd.h>
70 
71 #ifdef HAS_FCNTL_LOCK
72 #include <fcntl.h>
73 #include <string.h>
74 #endif
75 
76 #ifdef HAS_FLOCK_LOCK
77 #include <sys/file.h>
78 #endif
79 
80 /* Utility library. */
81 
82 #include "msg.h"
83 #include "myflock.h"
84 
85 /* myflock - lock/unlock entire open file */
86 
87 int myflock(int fd, int lock_style, int operation)
88 {
89  int status;
90 
91  /*
92  * Sanity check.
93  */
94  if ((operation & (MYFLOCK_OP_BITS)) != operation)
95  msg_panic("myflock: improper operation type: 0x%x", operation);
96 
97  switch (lock_style) {
98 
99  /*
100  * flock() does exactly what we need. Too bad it is not standard.
101  */
102 #ifdef HAS_FLOCK_LOCK
103  case MYFLOCK_STYLE_FLOCK:
104  {
105  static int lock_ops[] = {
106  LOCK_UN, LOCK_SH, LOCK_EX, -1,
107  -1, LOCK_SH | LOCK_NB, LOCK_EX | LOCK_NB, -1
108  };
109 
110  while ((status = flock(fd, lock_ops[operation])) < 0
111  && errno == EINTR)
112  sleep(1);
113  break;
114  }
115 #endif
116 
117  /*
118  * fcntl() is standard and does more than we need, but we can handle
119  * it.
120  */
121 #ifdef HAS_FCNTL_LOCK
122  case MYFLOCK_STYLE_FCNTL:
123  {
124  struct flock lock;
125  int request;
126  static int lock_ops[] = {
127  F_UNLCK, F_RDLCK, F_WRLCK
128  };
129 
130  memset((void *) &lock, 0, sizeof(lock));
131  lock.l_type = lock_ops[operation & ~MYFLOCK_OP_NOWAIT];
132  request = (operation & MYFLOCK_OP_NOWAIT) ? F_SETLK : F_SETLKW;
133  while ((status = fcntl(fd, request, &lock)) < 0
134  && errno == EINTR)
135  sleep(1);
136  break;
137  }
138 #endif
139  default:
140  msg_panic("myflock: unsupported lock style: 0x%x", lock_style);
141  }
142 
143  /*
144  * Return a consistent result. Some systems return EACCES when a lock is
145  * taken by someone else, and that would complicate error processing.
146  */
147  if (status < 0 && (operation & MYFLOCK_OP_NOWAIT) != 0)
148  if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EACCES)
149  errno = EAGAIN;
150 
151  return (status);
152 }
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define MYFLOCK_OP_NOWAIT
Definition: myflock.h:31
int myflock(int fd, int lock_style, int operation)
Definition: myflock.c:87
#define MYFLOCK_STYLE_FLOCK
Definition: myflock.h:22
#define MYFLOCK_OP_BITS
Definition: myflock.h:33
#define MYFLOCK_STYLE_FCNTL
Definition: myflock.h:23