Merge branch 'vipw-shortwrite' of https://github.com/DankRank/util-linux
* 'vipw-shortwrite' of https://github.com/DankRank/util-linux: ul_copy_file: make defines for return values read_all: return 0 when EOF occurs after 0 bytes ul_copy_file: add test program ul_copy_file: handle EAGAIN and EINTR ul_copy_file: use all_read/all_write ul_copy_file: use BUFSSIZ for buffer size nologin: use ul_copy_file login: use ul_copy_file configure.ac: check for sendfile ul_copy_file: use sendfile vipw: move copyfile to the lib vipw: fix short write handling in copyfile
This commit is contained in:
commit
bb123ad503
|
@ -530,6 +530,7 @@ AC_CHECK_FUNCS([ \
|
|||
qsort_r \
|
||||
rpmatch \
|
||||
scandirat \
|
||||
sendfile \
|
||||
setprogname \
|
||||
setresgid \
|
||||
setresuid \
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SENDFILE
|
||||
#include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
#include "c.h"
|
||||
|
||||
|
@ -63,13 +67,15 @@ static inline ssize_t read_all(int fd, char *buf, size_t count)
|
|||
memset(buf, 0, count);
|
||||
while (count > 0) {
|
||||
ret = read(fd, buf, count);
|
||||
if (ret <= 0) {
|
||||
if (ret < 0 && (errno == EAGAIN || errno == EINTR) && (tries++ < 5)) {
|
||||
if (ret < 0) {
|
||||
if ((errno == EAGAIN || errno == EINTR) && (tries++ < 5)) {
|
||||
xusleep(250000);
|
||||
continue;
|
||||
}
|
||||
return c ? c : -1;
|
||||
}
|
||||
if (ret == 0)
|
||||
return c;
|
||||
tries = 0;
|
||||
count -= ret;
|
||||
buf += ret;
|
||||
|
@ -78,4 +84,32 @@ static inline ssize_t read_all(int fd, char *buf, size_t count)
|
|||
return c;
|
||||
}
|
||||
|
||||
static inline ssize_t sendfile_all(int out, int in, off_t *off, size_t count)
|
||||
{
|
||||
#ifdef HAVE_SENDFILE
|
||||
ssize_t ret;
|
||||
ssize_t c = 0;
|
||||
int tries = 0;
|
||||
while (count) {
|
||||
ret = sendfile(out, in, off, count);
|
||||
if (ret < 0) {
|
||||
if ((errno == EAGAIN || errno == EINTR) && (tries++ < 5)) {
|
||||
xusleep(250000);
|
||||
continue;
|
||||
}
|
||||
return c ? c : -1;
|
||||
}
|
||||
if (ret == 0)
|
||||
return c;
|
||||
tries = 0;
|
||||
count -= ret;
|
||||
c += ret;
|
||||
}
|
||||
return c;
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* UTIL_LINUX_ALL_IO_H */
|
||||
|
|
|
@ -74,4 +74,8 @@ static inline struct dirent *xreaddir(DIR *dp)
|
|||
|
||||
extern void close_all_fds(const int exclude[], size_t exsz);
|
||||
|
||||
#define UL_COPY_READ_ERROR (-1)
|
||||
#define UL_COPY_WRITE_ERROR (-2)
|
||||
int ul_copy_file(int from, int to);
|
||||
|
||||
#endif /* UTIL_LINUX_FILEUTILS */
|
||||
|
|
|
@ -6,12 +6,15 @@
|
|||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "c.h"
|
||||
#include "all-io.h"
|
||||
#include "fileutils.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
|
@ -174,7 +177,7 @@ void close_all_fds(const int exclude[], size_t exsz)
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
errx(EXIT_FAILURE, "Usage %s --{mkstemp,close-fds}", argv[0]);
|
||||
errx(EXIT_FAILURE, "Usage %s --{mkstemp,close-fds,copy-file}", argv[0]);
|
||||
|
||||
if (strcmp(argv[1], "--mkstemp") == 0) {
|
||||
FILE *f;
|
||||
|
@ -194,6 +197,12 @@ int main(int argc, char *argv[])
|
|||
ignore_result( dup(STDIN_FILENO) );
|
||||
|
||||
close_all_fds(wanted_fds, ARRAY_SIZE(wanted_fds));
|
||||
} else if (strcmp(argv[1], "--copy-file") == 0) {
|
||||
int ret = ul_copy_file(STDIN_FILENO, STDOUT_FILENO);
|
||||
if (ret == UL_COPY_READ_ERROR)
|
||||
err(EXIT_FAILURE, "read");
|
||||
else if (ret == UL_COPY_WRITE_ERROR)
|
||||
err(EXIT_FAILURE, "write");
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -246,3 +255,42 @@ char *stripoff_last_component(char *path)
|
|||
*p = '\0';
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
static int copy_file_simple(int from, int to)
|
||||
{
|
||||
ssize_t nr;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
while ((nr = read_all(from, buf, sizeof(buf))) > 0)
|
||||
if (write_all(to, buf, nr) == -1)
|
||||
return UL_COPY_WRITE_ERROR;
|
||||
if (nr < 0)
|
||||
return UL_COPY_READ_ERROR;
|
||||
#ifdef HAVE_EXPLICIT_BZERO
|
||||
explicit_bzero(buf, sizeof(buf));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copies the contents of a file. Returns -1 on read error, -2 on write error. */
|
||||
int ul_copy_file(int from, int to)
|
||||
{
|
||||
#ifdef HAVE_SENDFILE
|
||||
struct stat st;
|
||||
ssize_t nw;
|
||||
|
||||
if (fstat(from, &st) == -1)
|
||||
return UL_COPY_READ_ERROR;
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return copy_file_simple(from, to);
|
||||
if (sendfile_all(to, from, NULL, st.st_size) < 0)
|
||||
return copy_file_simple(from, to);
|
||||
/* ensure we either get an EOF or an error */
|
||||
while ((nw = sendfile_all(to, from, NULL, 16*1024*1024)) != 0)
|
||||
if (nw < 0)
|
||||
return copy_file_simple(from, to);
|
||||
return 0;
|
||||
#else
|
||||
return copy_file_simple(from, to);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ if BUILD_NOLOGIN
|
|||
sbin_PROGRAMS += nologin
|
||||
dist_man_MANS += login-utils/nologin.8
|
||||
nologin_SOURCES = login-utils/nologin.c
|
||||
nologin_LDADD = $(LDADD) libcommon.la
|
||||
endif
|
||||
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
#elif defined(HAVE_SECURITY_OPENPAM_H)
|
||||
# include <security/openpam.h>
|
||||
#endif
|
||||
#include <sys/sendfile.h>
|
||||
|
||||
#ifdef HAVE_LIBAUDIT
|
||||
# include <libaudit.h>
|
||||
|
@ -345,9 +344,7 @@ static int motddir(const char *dirname)
|
|||
|
||||
fd = openat(dd, d->d_name, O_RDONLY|O_CLOEXEC);
|
||||
if (fd >= 0) {
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) == 0 && st.st_size > 0)
|
||||
sendfile(fileno(stdout), fd, NULL, st.st_size);
|
||||
ul_copy_file(fd, fileno(stdout));
|
||||
close(fd);
|
||||
done++;
|
||||
}
|
||||
|
@ -396,7 +393,7 @@ static void motd(void)
|
|||
if (S_ISREG(st.st_mode) && st.st_size > 0) {
|
||||
int fd = open(file, O_RDONLY, 0);
|
||||
if (fd >= 0) {
|
||||
sendfile(fileno(stdout), fd, NULL, st.st_size);
|
||||
ul_copy_file(fd, fileno(stdout));
|
||||
close(fd);
|
||||
}
|
||||
done++;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "c.h"
|
||||
#include "nls.h"
|
||||
#include "pathnames.h"
|
||||
#include "fileutils.h"
|
||||
|
||||
/*
|
||||
* Always return EXIT_FAILURE (1), don't try to be smart!
|
||||
|
@ -97,12 +98,7 @@ int main(int argc, char *argv[])
|
|||
if (c < 0 || !S_ISREG(st.st_mode))
|
||||
goto dflt;
|
||||
else {
|
||||
char buf[BUFSIZ];
|
||||
ssize_t rd;
|
||||
|
||||
while ((rd = read(fd, buf, sizeof(buf))) > 0)
|
||||
ignore_result( write(STDOUT_FILENO, buf, rd) );
|
||||
|
||||
ul_copy_file(fd, STDOUT_FILENO);
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
|
@ -88,23 +88,6 @@ static char *tmp_file; /* tmp file */
|
|||
|
||||
void pw_error (char *, int, int);
|
||||
|
||||
static void copyfile(int from, int to)
|
||||
{
|
||||
int nr, nw, off;
|
||||
char buf[8 * 1024];
|
||||
|
||||
while ((nr = read(from, buf, sizeof(buf))) > 0)
|
||||
for (off = 0; off < nr; nr -= nw, off += nw)
|
||||
if ((nw = write(to, buf + off, nr)) < 0)
|
||||
pw_error(tmp_file, 1, 1);
|
||||
|
||||
if (nr < 0)
|
||||
pw_error(orig_file, 1, 1);
|
||||
#ifdef HAVE_EXPLICIT_BZERO
|
||||
explicit_bzero(buf, sizeof(buf));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void pw_init(void)
|
||||
{
|
||||
struct rlimit rlim;
|
||||
|
@ -139,14 +122,19 @@ static FILE * pw_tmpfile(int lockfd)
|
|||
{
|
||||
FILE *fd;
|
||||
char *tmpname = NULL;
|
||||
int res;
|
||||
|
||||
if ((fd = xfmkstemp(&tmpname, "/etc", ".vipw")) == NULL) {
|
||||
ulckpwdf();
|
||||
err(EXIT_FAILURE, _("can't open temporary file"));
|
||||
}
|
||||
|
||||
copyfile(lockfd, fileno(fd));
|
||||
tmp_file = tmpname;
|
||||
res = ul_copy_file(lockfd, fileno(fd));
|
||||
if (res == UL_COPY_READ_ERROR)
|
||||
pw_error(orig_file, 1, 1);
|
||||
else if (res == UL_COPY_WRITE_ERROR)
|
||||
pw_error(tmp_file, 1, 1);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue