pid = getpid ();
snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
len = (ssize_t) strlen (buf) + 1;
- if (write_full (fd, buf, (size_t) len) != len) {
+ if (write_full(fd, buf, len) == -1) {
if (log) {
(void) fprintf (shadow_logfd,
"%s: %s file write error: %s\n",
extern bool valid (const char *, const struct passwd *);
/* write_full.c */
-extern ssize_t write_full(int fd, const void *buf, size_t count);
+extern int write_full(int fd, const void *buf, size_t count);
/* xgetpwnam.c */
extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *);
/*
- * SPDX-FileCopyrightText: 2023, Christian Göttsche <cgzones@googlemail.com>
+ * SPDX-FileCopyrightText: 2023, Christian Göttsche <cgzones@googlemail.com>
+ * SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
*
- * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-License-Identifier: BSD-3-Clause
*/
#ident "$Id$"
-#include "prototypes.h"
-
#include <errno.h>
#include <unistd.h>
+#include "prototypes.h"
+
/*
- * write_full - write entire buffer
+ * SYNOPSIS
+ * int write_full(int fd, const void *buf, size_t count);
+ *
+ * ARGUMENTS
+ * fd File descriptor.
+ * buf Source buffer to write(2) into 'fd'.
+ * count Size of 'buf'.
+ *
+ * DESCRIPTION
+ * Write 'count' bytes from the buffer starting at 'buf' to the
+ * file referred to by 'fd'.
+ *
+ * This function is similar to write(2), except that it retries
+ * in case of a short write.
+ *
+ * Since this function either performs a full write, or fails, the
+ * return value is simpler than for write(2).
*
- * Write up to count bytes from the buffer starting at buf to the
- * file referred to by the file descriptor fd.
- * Retry in case of a short write.
+ * RETURN VALUE
+ * 0 On success.
+ * -1 On error.
*
- * Returns the number of bytes written on success, -1 on error.
+ * ERRORS
+ * See write(2).
+ *
+ * CAVEATS
+ * This function can still perform partial writes: if the function
+ * fails in the loop after one or more write(2) calls have
+ * succeeded, it will report a failure, but some data may have been
+ * written. In such a case, it's the caller's responsibility to
+ * make sure that the partial write is not problematic, and
+ * remediate it if it is --maybe by trying to remove the file--.
*/
-ssize_t write_full(int fd, const void *buf, size_t count) {
- ssize_t written = 0;
- while (count > 0) {
- ssize_t res;
- res = write(fd, buf, count);
- if (res < 0) {
- if (errno == EINTR) {
- continue;
- }
+int
+write_full(int fd, const void *buf, size_t count)
+{
+ ssize_t w;
+ const unsigned char *p;
- return res;
- }
+ p = buf;
+
+ while (count > 0) {
+ w = write(fd, p, count);
+ if (w == -1) {
+ if (errno == EINTR)
+ continue;
- if (res == 0) {
- break;
+ return -1;
}
- written += res;
- buf = (const unsigned char*)buf + res;
- count -= res;
+ p += w;
+ count -= w;
}
- return written;
+ return 0;
}
break;
}
- if (write_full (ofd, buf, cnt) < 0) {
+ if (write_full(ofd, buf, cnt) == -1) {
(void) close (ofd);
(void) close (ifd);
return -1;
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
- || (write_full (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)
+ || (write_full(fd, fl, sizeof *fl) == -1)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't write faillog entry for UID %lu in %s.",
fail.fail_cnt = 0;
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
- || (write_full (fd, &fail, sizeof fail) != (ssize_t) sizeof fail)
+ || (write_full(fd, &fail, sizeof fail) == -1)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't reset faillog entry for UID %lu in %s.",
log_get_progname(), map_file, strerror(errno));
exit(EXIT_FAILURE);
}
- if (write_full(fd, buf, pos - buf) != (pos - buf)) {
+ if (write_full(fd, buf, pos - buf) == -1) {
fprintf(log_get_logfd(), _("%s: write to %s failed: %s\n"),
log_get_progname(), map_file, strerror(errno));
exit(EXIT_FAILURE);
strncpy (newlog.ll_host, host, sizeof (newlog.ll_host) - 1);
#endif
if ( (lseek (fd, offset, SEEK_SET) != offset)
- || (write_full (fd, &newlog, sizeof newlog) != (ssize_t) sizeof newlog)
+ || (write_full(fd, &newlog, sizeof newlog) == -1)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't write lastlog entry for UID %lu in %s.",
* Append the new failure record and close the log file.
*/
- if ( (write_full (fd, failent, sizeof *failent) != (ssize_t) sizeof *failent)
+ if ( (write_full(fd, failent, sizeof *failent) == -1)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't append failure of user %s to %s.",
fd = open (filename, O_APPEND | O_WRONLY, 0);
if (fd >= 0) {
- write_full (fd, ut, sizeof (*ut));
+ write_full(fd, ut, sizeof(*ut));
close (fd);
}
}
static void alarm_handler (unused int sig)
{
- write_full (STDERR_FILENO, tmsg, strlen (tmsg));
+ write_full(STDERR_FILENO, tmsg, strlen(tmsg));
signal(SIGALRM, exit_handler);
alarm(2);
}
{
if (0 != pid_child) {
(void) kill (-pid_child, SIGKILL);
- (void) write_full (STDERR_FILENO, kill_msg, strlen (kill_msg));
+ (void) write_full(STDERR_FILENO, kill_msg, strlen(kill_msg));
} else {
- (void) write_full (STDERR_FILENO, wait_msg, strlen (wait_msg));
+ (void) write_full(STDERR_FILENO, wait_msg, strlen(wait_msg));
}
_exit (255);
}
return;
}
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
- || (write_full (fd, &fl, sizeof (fl)) != (ssize_t) sizeof (fl))
+ || (write_full(fd, &fl, sizeof (fl)) == -1)
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to reset the faillog entry of UID %lu: %s\n"),
&& (read (fd, &ll, sizeof ll) == (ssize_t) sizeof ll)) {
/* Copy the old entry to its new location */
if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
- || (write_full (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
+ || (write_full(fd, &ll, sizeof ll) == -1)
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
/* Reset the new uid's lastlog entry */
memzero (&ll, sizeof (ll));
if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
- || (write_full (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
+ || (write_full(fd, &ll, sizeof ll) == -1)
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
&& (read (fd, &fl, sizeof fl) == (ssize_t) sizeof fl)) {
/* Copy the old entry to its new location */
if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
- || (write_full (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)
+ || (write_full(fd, &fl, sizeof fl) == -1)
|| (fsync (fd) != 0)) {
fprintf (stderr,
_("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"),
/* Reset the new uid's faillog entry */
memzero (&fl, sizeof (fl));
if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
- || (write_full (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)) {
+ || (write_full(fd, &fl, sizeof fl) == -1))
+ {
fprintf (stderr,
_("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"),
Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno));