UPS: apcupsd clean sources
[tomato.git] / release / src / router / apcupsd / src / lib / apclock.c
blobaa3b90889ba20ec960003469d5fed3a67c212356
1 /*
2 * apclock.c
4 * Lock file managing functions.
5 */
7 /*
8 * Copyright (C) 2000-2006 Kern Sibbald
9 * Copyright (C) 1998-99 Brian Schau <bsc@fleggaard.dk>
10 * Copyright (C) 1998-99-2000 Riccardo Facchetti <riccardo@master.oasi.gpa.it>
11 * Copyright (C) 1996-99 Andre M. Hedrick <andre@suse.com>
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of version 2 of the GNU General
15 * Public License as published by the Free Software Foundation.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public
23 * License along with this program; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
28 #include "apc.h"
30 /*
31 * For Windows, we do NOT create a lock file. Even if we did
32 * no other program would respect it since this is not a
33 * Unix system.
36 /* Check to see if a serial port lockfile exists.
37 * If so, and the process is no longer running,
38 * blow away the lockfile.
40 #if !defined(HAVE_WIN32)
41 static int check_stale_lockfile(UPSINFO *ups)
43 char pidbuffer[12];
44 int size;
45 int stalepid;
46 int error;
49 * If the daemon is talking with APC_NET, the lock file is not
50 * needed.
52 if (ups->cable.type == APC_NET)
53 return LCKNOLOCK;
55 if (ups->lockpath[0] == '\0') {
57 * If there's no lockfile configured, return error.
58 * This is a _must_. See my comment in apcconfig.c
60 log_event(ups, LOG_ERR, "No lock path configured.\n");
61 return LCKERROR;
64 errno = 0;
65 if ((ups->lockfile = open(ups->lockpath, O_RDONLY)) < 0) {
67 * Cannot open the file (may be it doesn't exist and that's okay
68 * for us so return success).
70 if (errno == ENOENT)
71 return LCKSUCCESS;
73 /* On any other error, return error. */
74 log_event(ups, LOG_ERR, "Lock file open error. ERR=%s\n", strerror(errno));
75 return LCKERROR;
78 if ((size = read(ups->lockfile, &pidbuffer, 11)) == -1) {
80 * If we can not read from file, close it and return error:
81 * the file exist but we can not check for stale.
83 error = LCKERROR;
84 log_event(ups, LOG_ERR, "Lock file read error. ERR=%s\n", strerror(errno));
85 goto out;
88 if (size == 0 || (sscanf(pidbuffer, "%d", &stalepid) != 1)) {
90 * If there's no data in the file or the data written is wrong
91 * we have a process that:
92 * 1 - running but failed to write the lock file
93 * 2 - not running and failed to write the lock file
95 * Anyway we assume the worst case (1) and return error.
97 error = LCKERROR;
98 log_event(ups, LOG_ERR, "Lock file data error: %s\n", pidbuffer);
99 goto out;
102 /* Check if it is our current pid or the pid of our parent */
103 if (stalepid == getpid() || stalepid == getppid()) {
105 * We are us (may be a crash of the machine ... same pid
106 * because same boot sequence ... leave it alone and go run)
108 error = LCKEXIST;
109 goto out;
113 * Okay, now we have a stalepid to check.
114 * kill(pid,0) checks to see if the process is still running.
116 if (kill(stalepid, 0) == -1 && errno == ESRCH) {
118 * Okay this is a stale lock:
119 * we can unlink even before closing it.
121 if (unlink(ups->lockpath) < 0) {
122 log_event(ups, LOG_ERR,
123 "Unable to unlink old lock file %s because %s\n",
124 ups->lockpath, strerror(errno));
125 error = LCKERROR;
126 } else {
127 error = LCKSUCCESS;
129 goto out;
133 * We have unfortunately found a perfectly valid lock file.
134 * Don't touch it.
136 log_event(ups, LOG_ERR, "Valid lock file for pid=%d, but not ours pid=%d\n",
137 stalepid, getpid());
139 error = LCKERROR;
141 out:
142 close(ups->lockfile);
143 ups->lockfile = -1;
145 return error;
147 #endif
150 * Create serial port lock file
152 int hibernate_ups = FALSE;
153 int shutdown_ups = FALSE;
154 int create_lockfile(UPSINFO *ups)
156 #if !defined(HAVE_WIN32)
157 char pidbuffer[12];
158 int error;
161 * If this is a hibernate or shutdown execution, we are
162 * probably running with the filesystems read-only, so
163 * don't try to create the lock file.
165 if (hibernate_ups || shutdown_ups)
166 return LCKSUCCESS;
168 switch (error = check_stale_lockfile(ups)) {
169 case LCKNOLOCK:
170 /* Lockfile not needed: return success. */
171 case LCKEXIST:
172 /* Lockfile exists and contains our pid. */
173 return LCKSUCCESS;
175 case LCKERROR:
176 /* Lockfile exists and is not stale. */
177 return LCKERROR;
179 case LCKSUCCESS:
180 /* Lockfile does not exist _now_. */
181 break;
186 * Now the file does not exist any more.
187 * Open it for creation and don't accept any kind of error.
189 errno = 0;
190 if ((ups->lockfile = open(ups->lockpath, O_CREAT | O_EXCL | O_RDWR, 0644)) < 0) {
192 * Okay there is some problem with the lock path or
193 * something like that.
195 log_event(ups, LOG_ERR,
196 "Cannot create %s serial port lock file: ERR=%s\n",
197 ups->lockpath, strerror(errno));
198 return LCKERROR;
201 if (asnprintf(pidbuffer, sizeof(pidbuffer), "%010ld", (long)getpid()) <= 0) {
202 /* Problems with sprintf */
203 error = LCKERROR;
204 log_event(ups, LOG_ERR, "Lock file sprintf error.\n");
205 goto out;
208 if (write(ups->lockfile, pidbuffer,
209 strlen(pidbuffer) + 1) != (int)strlen(pidbuffer) + 1) {
210 /* Problems with write. */
211 error = LCKERROR;
212 log_event(ups, LOG_ERR, "Lock file %s write failure. ERR=%s\n",
213 ups->lockpath, strerror(errno));
214 goto out;
217 /* Done it. */
218 error = LCKSUCCESS;
220 out:
222 close(ups->lockfile);
223 ups->lockfile = -1;
224 return error;
226 #else
227 return LCKSUCCESS;
228 #endif
231 void delete_lockfile(UPSINFO *ups)
233 #if !defined(HAVE_WIN32)
234 if (ups->lockpath[0] != '\0') {
236 * If lockfile is ours, close it and delete it,
237 * otherwise do nothing.
239 if (check_stale_lockfile(ups) == LCKEXIST) {
240 if (ups->lockfile != -1) {
241 close(ups->lockfile);
242 ups->lockfile = -1;
244 unlink(ups->lockpath);
247 * Now ups->lockfile is == -1 so there's no need to
248 * blank ups->lockfile too.
251 #endif