4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
42 #include <sys/types.h>
43 #include <sys/signal.h>
44 #include <sys/fault.h>
45 #include <sys/syscall.h>
54 #define LOCKFILE ".lockfile"
56 #define LOCKWAIT 20 /* seconds between retries */
57 #define LOCKRETRY 10 /* number of retries for a DB lock */
58 #define LF_SIZE 128 /* size of governing lock file */
60 #define MSG_WTING "NOTE: Waiting for access to the package database."
61 #define MSG_XWTING "NOTE: Waiting for exclusive access to the package " \
63 #define MSG_WTFOR "NOTE: Waiting for %s of %s to complete."
64 #define WRN_CLRLOCK "WARNING: Stale lock installed for %s, pkg %s quit " \
66 #define WRN_CLRLOCK1 "Removing lock."
67 #define ERR_MKLOCK "unable to create governing lock file <%s>."
68 #define ERR_NOLOCK "unable to install governing lock on <%s>."
69 #define ERR_NOOPEN "unable to open <%s>."
70 #define ERR_LCKTBL "unable to lock <%s> - lock table full."
71 #define ERR_LCKREM "unable to lock <%s> - remote host unavailable."
72 #define ERR_BADLCK "unable to lock <%s> - unknown error."
73 #define ERR_DEADLCK "unable to lock <%s> - deadlock condition."
75 static pid_t lock_pid
;
76 static int lock_fd
, lock_is_applied
;
77 static char lock_name
[PKGSIZ
];
78 static char lock_pkg
[PKGSIZ
];
79 static char lock_place
[PKGSIZ
];
80 static unsigned int lock_state
;
81 static char lockbuf
[LCKBUFSIZ
];
82 static char lockpath
[PATH_MAX
];
84 #define LOCK_NAME_OLD_PKG "old version pkg command"
85 #define LOCK_PKG_UNKNOWN "unknown package"
86 #define LOCK_PLACE_UNKNOWN "unknown"
89 * This function writes the PID, effective utility name, package name,
90 * current progress of the utility and the exit state to the lockfile in
91 * support of post mortem operations.
94 wrlockdata(int fd
, int this_pid
, char *this_name
,
95 char *this_pkg
, char *this_place
, unsigned int this_state
)
97 if (this_pid
< 0 || *this_name
== '\000')
100 (void) memset(lockbuf
, 0, LCKBUFSIZ
);
102 (void) snprintf(lockbuf
, sizeof (lockbuf
),
103 "%d %s %s %s %d\n", this_pid
, this_name
, this_pkg
,
104 this_place
, this_state
);
106 (void) lseek(fd
, 0, SEEK_SET
);
107 if (write(fd
, lockbuf
, LF_SIZE
) == LF_SIZE
)
114 * This function reads the lockfile to obtain the PID and name of the lock
115 * holder. Upon those rare circumstances that an older version of pkgadd
116 * created the lock, this detects that zero-length file and provides the
117 * appropriate data. Since this data is only used if an actual lock (from
118 * lockf()) is detected, a manually created .lockfile will not result in a
124 (void) lseek(fd
, 0, SEEK_SET
);
125 if (read(fd
, lockbuf
, LF_SIZE
) != LF_SIZE
) {
127 (void) strlcpy(lock_name
, LOCK_NAME_OLD_PKG
,
130 (void) strlcpy(lock_pkg
, LOCK_PKG_UNKNOWN
,
133 (void) strlcpy(lock_place
, LOCK_PLACE_UNKNOWN
,
134 sizeof (lock_place
));
138 /* LINTED format argument contains unbounded string specifier */
139 (void) sscanf(lockbuf
, "%ld %s %s %s %u", &lock_pid
,
140 lock_name
, lock_pkg
, lock_place
, &lock_state
);
151 (void) signal(SIGALRM
, do_alarm
);
152 (void) alarm(LOCKWAIT
);
156 * This establishes a locked status file for a pkgadd, pkgrm or swmtool - any
157 * of the complex package processes. Since numerous packages currently use
158 * installf and removef in preinstall scripts, we can't enforce a contents
159 * file write lock throughout the install process. In 2.7 we will enforce the
160 * write lock and allow this lock to serve as a simple information carrier
161 * which can be used by installf and removef too.
163 * util_name - the name of the utility that is claiming the lock
164 * pkg_name - the package that is being locked (or "all package")
165 * place - a string of ascii characters that defines the initial "place" where
166 * the current operation is - this is updated by lockupd() and is a string
167 * is used fr post mortem operations if the utility should quit improperly.
174 lockinst(char *util_name
, char *pkg_name
, char *place
)
178 /* assume "initial" if no "place" during processing specified */
180 if ((place
== (char *)NULL
) || (*place
== '\0')) {
184 (void) snprintf(lockpath
, sizeof (lockpath
),
185 "%s/%s", get_PKGADM(), LOCKFILE
);
187 /* If the exit file is not present, create it. */
188 /* LINTED O_CREAT without O_EXCL specified in call to open() */
189 if ((fd
= open(lockpath
, O_RDWR
| O_CREAT
, 0600)) == -1) {
190 progerr(gettext(ERR_MKLOCK
), lockpath
);
196 retry_cnt
= LOCKRETRY
;
199 (void) signal(SIGALRM
, do_alarm
);
200 (void) alarm(LOCKWAIT
);
203 * This tries to create the lock LOCKRETRY times waiting LOCKWAIT
204 * seconds between retries.
208 if (lockf(fd
, F_LOCK
, 0)) {
210 * Try to read the status of the last (or current)
215 logerr(gettext(MSG_WTFOR
), lock_name
, lock_pkg
);
216 } else { /* This process has the lock. */
219 if (lock_state
!= 0) {
220 logerr(gettext(WRN_CLRLOCK
), lock_name
,
221 lock_pkg
, lock_place
);
222 logerr(gettext(WRN_CLRLOCK1
));
226 (void) strlcpy(lock_name
, (util_name
) ?
227 util_name
: gettext("unknown"), sizeof (lock_name
));
229 (void) strlcpy(lock_pkg
, (pkg_name
) ?
230 pkg_name
: gettext("unknown"), sizeof (lock_pkg
));
232 (void) wrlockdata(fd
, lock_pid
, lock_name
,
233 lock_pkg
, place
, ST_QUIT
);
237 } while (retry_cnt
--);
239 (void) signal(SIGALRM
, SIG_IGN
);
241 if (!lock_is_applied
) {
242 progerr(gettext(ERR_NOLOCK
), lockpath
);
250 * This function updates the utility progress data in the lock file. It is
251 * used for post mortem operations if the utility should quit improperly.
256 (void) wrlockdata(lock_fd
, lock_pid
, lock_name
, lock_pkg
, place
,
261 * This clears the governing lock and closes the lock file. If this was
262 * called already, it just returns.
267 if (lock_is_applied
) {
268 (void) wrlockdata(lock_fd
, lock_pid
, lock_name
, lock_pkg
,
272 * If close() fails, we can't be sure the lock has been
273 * removed, so we assume the worst in case this function is
276 if (close(lock_fd
) != -1)