New calling convention for safe_read and full_write.

This commit is contained in:
Bruno Haible 2002-11-22 22:12:02 +00:00
parent 02df1aa0c0
commit 6c8f15797c
13 changed files with 220 additions and 90 deletions

View File

@ -1,5 +1,16 @@
2002-11-22 Bruno Haible <bruno@clisp.org>
* safe-write.h: New file, from current gnulib version.
* safe-write.c: New file, from current gnulib version.
* full-write.h: Update from current gnulib version.
* full-write.c: Update from current gnulib version.
* copy-file.c (copy_file): Change test of full_write return value.
* Makefile.am (libgettextlib_la_SOURCES): Add safe-write.h,
safe-write.c.
* safe-read.h: Update from current gnulib version.
* safe-read.c: Update from current gnulib version.
* argmatch.h: Update from current gnulib version.
* argmatch.c: Update from current gnulib version, with simplifications.

View File

@ -53,6 +53,7 @@ libgettextlib_la_SOURCES = \
pipe.h pipe-bidi.c pipe-in.c pipe-out.c \
progname.h progname.c \
safe-read.h safe-read.c \
safe-write.h safe-write.c \
sh-quote.h sh-quote.c \
stpncpy.h stpncpy.c \
strtoul.c \

View File

@ -81,7 +81,7 @@ copy_file (const char *src_filename, const char *dest_filename)
if (n_read == 0)
break;
if (full_write (dest_fd, buf, n_read) < 0)
if (full_write (dest_fd, buf, n_read) < n_read)
error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename);
}

View File

@ -1,5 +1,7 @@
/* full-write.c -- an interface to write that retries after interrupts
Copyright (C) 1993-1994, 1997-1998, 2000-2002 Free Software Foundation, Inc.
/* An interface to write() that writes all it is asked to write.
Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -13,10 +15,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Copied largely from GNU C's cccp.c.
*/
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
@ -25,45 +24,43 @@
/* Specification. */
#include "full-write.h"
#include <sys/types.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <errno.h>
#ifndef errno
extern int errno;
#endif
/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
Return LEN upon success, write's (negative) error code otherwise. */
#include "safe-write.h"
ssize_t
full_write (int desc, const char *ptr, size_t len)
/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
or if partial writes occur. Return the number of bytes successfully
written, setting errno if that is less than COUNT. */
size_t
full_write (int fd, const void *buf, size_t count)
{
int total_written;
size_t total_written = 0;
total_written = 0;
while (len > 0)
if (count > 0)
{
ssize_t written = write (desc, ptr, len);
/* write on an old Slackware Linux 1.2.13 returns zero when
I try to write more data than there is room on a floppy disk.
This puts dd into an infinite loop. Reproduce with
dd if=/dev/zero of=/dev/fd0. If you have this problem,
consider upgrading to a newer kernel. */
if (written < 0)
const char *ptr = buf;
do
{
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
return written;
size_t written = safe_write (fd, ptr, count);
if (written == (size_t)-1)
break;
if (written == 0)
{
/* Some buggy drivers return 0 when you fall off a device's
end. (Example: Linux 1.2.13 on /dev/fd0.) */
errno = ENOSPC;
break;
}
total_written += written;
ptr += written;
count -= written;
}
total_written += written;
ptr += written;
len -= written;
while (count > 0);
}
return total_written;
}

View File

@ -1,6 +1,6 @@
/* write() wrapper.
Copyright (C) 2001-2002 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
/* An interface to write() that writes all it is asked to write.
Copyright (C) 2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -16,12 +16,9 @@
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Get ssize_t. */
#include <sys/types.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stddef.h>
/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
Return LEN upon success, write's (negative) error code otherwise. */
extern ssize_t full_write (int desc, const char *ptr, size_t len);
/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
or if partial writes occur. Return the number of bytes successfully
written, setting errno if that is less than COUNT. */
extern size_t full_write (int fd, const void *buf, size_t count);

View File

@ -1,5 +1,5 @@
/* safe-read.c -- an interface to read that retries after interrupts
Copyright (C) 1993-1994, 1998, 2001-2002 Free Software Foundation, Inc.
/* An interface to read() that retries after interrupts.
Copyright (C) 1993, 1994, 1998, 2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -13,8 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
@ -23,8 +22,8 @@
/* Specification. */
#include "safe-read.h"
/* Get ssize_t. */
#include <sys/types.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
@ -34,27 +33,51 @@
extern int errno;
#endif
/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
Return the actual number of bytes read, zero for EOF, or negative
#include <limits.h>
/* We don't pass an nbytes count > SSIZE_MAX to read() - POSIX says the
effect would be implementation-defined. Also we don't pass an nbytes
count > INT_MAX but <= SSIZE_MAX to read() - this triggers a bug in
Tru64 5.1. */
#define MAX_BYTES_TO_READ INT_MAX
/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted.
Return the actual number of bytes read, zero for EOF, or (size_t) -1
for an error. */
ssize_t
safe_read (int desc, void *ptr, size_t len)
size_t
safe_read (int fd, void *buf, size_t count)
{
ssize_t n_chars;
size_t total_read = 0;
if (len <= 0)
return len;
#ifdef EINTR
do
if (count > 0)
{
n_chars = read (desc, ptr, len);
}
while (n_chars < 0 && errno == EINTR);
#else
n_chars = read (desc, ptr, len);
#endif
char *ptr = (char *) buf;
do
{
size_t nbytes_to_read = count;
ssize_t result;
return n_chars;
/* Limit the number of bytes to read in one round, to avoid running
into unspecified behaviour. But keep the file pointer block
aligned when doing so. */
if (nbytes_to_read > MAX_BYTES_TO_READ)
nbytes_to_read = MAX_BYTES_TO_READ & ~8191;
result = read (fd, ptr, nbytes_to_read);
if (result < 0)
{
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
return result;
}
total_read += result;
ptr += result;
count -= result;
}
while (count > 0);
}
return total_read;
}

View File

@ -1,6 +1,5 @@
/* read() wrapper.
Copyright (C) 2001-2002 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
/* An interface to read() that retries after interrupts.
Copyright (C) 2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -16,13 +15,9 @@
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Get ssize_t. */
#include <sys/types.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stddef.h>
/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
Return the actual number of bytes read, zero for EOF, or negative
/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted.
Return the actual number of bytes read, zero for EOF, or (size_t) -1
for an error. */
extern ssize_t safe_read (int desc, void *ptr, size_t len);
extern size_t safe_read (int fd, void *buf, size_t count);

83
lib/safe-write.c Normal file
View File

@ -0,0 +1,83 @@
/* An interface to write() that retries after interrupts.
Copyright (C) 1993, 1994, 1998, 2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
/* Specification. */
#include "safe-write.h"
/* Get ssize_t. */
#include <sys/types.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#include <limits.h>
/* We don't pass an nbytes count > SSIZE_MAX to write() - POSIX says the
effect would be implementation-defined. Also we don't pass an nbytes
count > INT_MAX but <= SSIZE_MAX to write() - this triggers a bug in
Tru64 5.1. */
#define MAX_BYTES_TO_READ INT_MAX
/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted.
Return the actual number of bytes written, zero for EOF, or (size_t) -1
for an error. */
size_t
safe_write (int fd, const void *buf, size_t count)
{
size_t total_written = 0;
if (count > 0)
{
const char *ptr = (const char *) buf;
do
{
size_t nbytes_to_write = count;
ssize_t result;
/* Limit the number of bytes to write in one round, to avoid running
into unspecified behaviour. But keep the file pointer block
aligned when doing so. */
if (nbytes_to_write > MAX_BYTES_TO_READ)
nbytes_to_write = MAX_BYTES_TO_READ & ~8191;
result = write (fd, ptr, nbytes_to_write);
if (result < 0)
{
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
return result;
}
total_written += result;
ptr += result;
count -= result;
}
while (count > 0);
}
return total_written;
}

23
lib/safe-write.h Normal file
View File

@ -0,0 +1,23 @@
/* An interface to write() that retries after interrupts.
Copyright (C) 2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stddef.h>
/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted.
Return the actual number of bytes written, zero for EOF, or (size_t) -1
for an error. */
extern size_t safe_write (int fd, const void *buf, size_t count);

View File

@ -1,3 +1,9 @@
2002-11-22 Bruno Haible <bruno@clisp.org>
* msgexec.c (process_string): Change test of full_write return value.
* msggrep.c (is_string_selected): Likewise.
* urlget.c (cat_file): Likewise.
2002-11-14 Bruno Haible <bruno@clisp.org>
* x-php.c (phase3_getc): Initialize variable last_was_qmark.

View File

@ -292,13 +292,10 @@ nonintr_close (int fd)
static void
process_string (const message_ty *mp, const char *str, size_t len)
{
ssize_t nwritten;
if (strcmp (sub_name, "0") == 0)
{
/* Built-in command "0". */
nwritten = full_write (STDOUT_FILENO, str, len + 1);
if (nwritten != (ssize_t) (len + 1))
if (full_write (STDOUT_FILENO, str, len + 1) < len + 1)
error (EXIT_FAILURE, errno, _("write to stdout failed"));
}
else
@ -320,8 +317,7 @@ process_string (const message_ty *mp, const char *str, size_t len)
child = create_pipe_out (sub_name, sub_path, sub_argv, NULL, false, true,
fd);
nwritten = full_write (fd[0], str, len);
if (nwritten != (ssize_t) len)
if (full_write (fd[0], str, len) < len)
error (EXIT_FAILURE, errno,
_("write to %s subprocess failed"), sub_name);

View File

@ -534,15 +534,13 @@ is_string_selected (int grep_pass, const char *str, size_t len)
{
pid_t child;
int fd[1];
ssize_t nwritten;
int exitstatus;
/* Open a pipe to a grep subprocess. */
child = create_pipe_out ("grep", grep_path, grep_argv[grep_pass],
"/dev/null", false, true, fd);
nwritten = full_write (fd[0], str, len);
if (nwritten != (ssize_t) len)
if (full_write (fd[0], str, len) < len)
error (EXIT_FAILURE, errno,
_("write to grep subprocess failed"));

View File

@ -209,7 +209,7 @@ cat_file (const char *src_filename)
if (n_read == 0)
break;
if (full_write (STDOUT_FILENO, buf, n_read) < 0)
if (full_write (STDOUT_FILENO, buf, n_read) < n_read)
error (EXIT_FAILURE, errno, _("error writing stdout"));
}