diff options
Diffstat (limited to 'libc/pwd_grp/lckpwdf.c')
| -rw-r--r-- | libc/pwd_grp/lckpwdf.c | 99 |
1 files changed, 29 insertions, 70 deletions
diff --git a/libc/pwd_grp/lckpwdf.c b/libc/pwd_grp/lckpwdf.c index 0b0fb471b..9b2aebcce 100644 --- a/libc/pwd_grp/lckpwdf.c +++ b/libc/pwd_grp/lckpwdf.c @@ -15,9 +15,8 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ #include <features.h> #include <fcntl.h> @@ -28,22 +27,9 @@ #include <paths.h> #include <shadow.h> -/* Experimentally off - libc_hidden_proto(memset) */ -libc_hidden_proto(open) -libc_hidden_proto(fcntl) -libc_hidden_proto(close) -libc_hidden_proto(sigfillset) -libc_hidden_proto(sigaction) -libc_hidden_proto(sigprocmask) -libc_hidden_proto(sigaddset) -libc_hidden_proto(sigemptyset) -libc_hidden_proto(alarm) - -/* How long to wait for getting the lock before returning with an - error. */ +/* How long to wait for getting the lock before returning with an error. */ #define TIMEOUT 15 /* sec */ - /* File descriptor for lock file. */ static int lock_fd = -1; @@ -51,7 +37,6 @@ static int lock_fd = -1; #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); - /* Prototypes for local functions. */ static void noop_handler (int __sig); @@ -59,7 +44,6 @@ static void noop_handler (int __sig); int lckpwdf (void) { - int flags; sigset_t saved_set; /* Saved set of caught signals. */ struct sigaction saved_act; /* Saved signal action. */ sigset_t new_set; /* New set of caught signals. */ @@ -75,90 +59,65 @@ lckpwdf (void) /* Prevent problems caused by multiple threads. */ __UCLIBC_MUTEX_LOCK(mylock); - lock_fd = open (_PATH_PASSWD, O_WRONLY); + lock_fd = open (_PATH_PASSWD, O_WRONLY | O_CLOEXEC); if (lock_fd == -1) { - /* Cannot create lock file. */ - goto DONE; + goto DONE; } - +#ifndef __ASSUME_O_CLOEXEC /* Make sure file gets correctly closed when process finished. */ - flags = fcntl (lock_fd, F_GETFD, 0); - if (flags == -1) { - /* Cannot get file flags. */ - close(lock_fd); - lock_fd = -1; - goto DONE; - } - flags |= FD_CLOEXEC; /* Close on exit. */ - if (fcntl (lock_fd, F_SETFD, flags) < 0) { - /* Cannot set new flags. */ - close(lock_fd); - lock_fd = -1; - goto DONE; - } + fcntl (lock_fd, F_SETFD, FD_CLOEXEC); +#endif /* Now we have to get exclusive write access. Since multiple process could try this we won't stop when it first fails. Instead we set a timeout for the system call. Once the timer expires it is likely that there are some problems which cannot be - resolved by waiting. + resolved by waiting. (sa_flags have no SA_RESTART. Thus SIGALRM + will EINTR fcntl(F_SETLKW) It is important that we don't change the signal state. We must restore the old signal behaviour. */ - memset (&new_act, '\0', sizeof (struct sigaction)); + memset (&new_act, '\0', sizeof (new_act)); new_act.sa_handler = noop_handler; - sigfillset (&new_act.sa_mask); - new_act.sa_flags = 0ul; + __sigfillset (&new_act.sa_mask); - /* Install new action handler for alarm and save old. */ - if (sigaction (SIGALRM, &new_act, &saved_act) < 0) { - /* Cannot install signal handler. */ - close(lock_fd); - lock_fd = -1; - goto DONE; - } + /* Install new action handler for alarm and save old. + * This never fails in Linux. */ + sigaction (SIGALRM, &new_act, &saved_act); /* Now make sure the alarm signal is not blocked. */ - sigemptyset (&new_set); - sigaddset (&new_set, SIGALRM); - if (sigprocmask (SIG_UNBLOCK, &new_set, &saved_set) < 0) { - sigaction (SIGALRM, &saved_act, NULL); - close(lock_fd); - lock_fd = -1; - goto DONE; - } + __sigemptyset (&new_set); + __sigaddset (&new_set, SIGALRM); + sigprocmask (SIG_UNBLOCK, &new_set, &saved_set); /* Start timer. If we cannot get the lock in the specified time we get a signal. */ alarm (TIMEOUT); /* Try to get the lock. */ - memset (&fl, '\0', sizeof (struct flock)); - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; + memset (&fl, '\0', sizeof (fl)); + if (F_WRLCK) + fl.l_type = F_WRLCK; + if (SEEK_SET) + fl.l_whence = SEEK_SET; result = fcntl (lock_fd, F_SETLKW, &fl); /* Clear alarm. */ alarm (0); - /* Restore old set of handled signals. We don't need to know - about the current one.*/ sigprocmask (SIG_SETMASK, &saved_set, NULL); - - /* Restore old action handler for alarm. We don't need to know - about the current one. */ sigaction (SIGALRM, &saved_act, NULL); if (result < 0) { close(lock_fd); lock_fd = -1; - goto DONE; + goto DONE; } rv = 0; DONE: __UCLIBC_MUTEX_UNLOCK(mylock); - return 0; + return rv; } @@ -173,7 +132,7 @@ ulckpwdf (void) else { /* Prevent problems caused by multiple threads. */ - __UCLIBC_MUTEX_LOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); result = close (lock_fd); @@ -181,7 +140,7 @@ ulckpwdf (void) lock_fd = -1; /* Clear mutex. */ - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_UNLOCK(mylock); } return result; @@ -189,7 +148,7 @@ ulckpwdf (void) static void -noop_handler (int sig) -{ +noop_handler (int sig attribute_unused) { + /* We simply return which makes the `fcntl' call return with an error. */ } |
