Mail Archives: djgpp-workers/2003/03/09/12:02:13
Hello.
Here's revision 3 of the pwrite patch. The only change is that
we never fail for pipes now, since they are always regular files
under DJGPP.
OK to commit?
Thanks, bye, Rich =]
Index: include/unistd.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/unistd.h,v
retrieving revision 1.16
diff -p -c -3 -r1.16 unistd.h
*** include/unistd.h 4 Feb 2003 20:24:30 -0000 1.16
--- include/unistd.h 9 Mar 2003 16:45:10 -0000
*************** off_t lseek(int _fildes, off_t _offset,
*** 134,139 ****
--- 134,140 ----
long pathconf(const char *_path, int _name);
int pause(void);
int pipe(int _fildes[2]);
+ ssize_t pwrite(int _fildes, const void *_buf, size_t _nbyte, off_t _offset);
ssize_t read(int _fildes, void *_buf, size_t _nbyte);
int rmdir(const char *_path);
int setgid(gid_t _gid);
Index: src/libc/posix/unistd/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/unistd/makefile,v
retrieving revision 1.5
diff -p -c -3 -r1.5 makefile
*** src/libc/posix/unistd/makefile 14 Jun 2001 02:56:32 -0000 1.5
--- src/libc/posix/unistd/makefile 9 Mar 2003 16:45:10 -0000
***************
*** 1,3 ****
--- 1,4 ----
+ # Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details
# Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details
# Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details
# Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details
*************** SRC += lseek.c
*** 39,44 ****
--- 40,46 ----
SRC += pathconf.c
SRC += pause.c
SRC += pipe.c
+ SRC += pwrite.c
SRC += read.c
SRC += rmdir.c
SRC += setgid.c
Index: tests/libc/posix/unistd/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/libc/posix/unistd/makefile,v
retrieving revision 1.4
diff -p -c -3 -r1.4 makefile
*** tests/libc/posix/unistd/makefile 1 Mar 2003 13:17:36 -0000 1.4
--- tests/libc/posix/unistd/makefile 9 Mar 2003 16:45:13 -0000
*************** SRC += sleep.c
*** 9,13 ****
--- 9,15 ----
SRC += tread.c
SRC += write.c
SRC += t-isatty.c
+ SRC += t-lseek.c
+ SRC += t-pwrite.c
include $(TOP)/../makefile.inc
*** /dev/null Sun Mar 9 16:48:31 2003
--- src/libc/posix/unistd/pwrite.c Sun Mar 9 16:45:38 2003
***************
*** 0 ****
--- 1,57 ----
+ /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
+ #include <libc/stubs.h>
+ #include <errno.h>
+ #include <unistd.h>
+
+ ssize_t
+ pwrite (int fd, const void *buf, size_t nbyte, off_t offset)
+ {
+ offset_t start_pos, curr_pos;
+ int old_errno;
+ ssize_t ret;
+
+ /* TODO: When we support the Large File Summit, fail here, if the offset
+ * is negative. */
+ #if 0
+ if (offset < 0) {
+ errno = EINVAL;
+ return(-1);
+ }
+ #endif
+
+ /* Get the current position. */
+ start_pos = llseek(fd, 0LL, SEEK_CUR);
+ if (start_pos == -1)
+ return(-1); /* Pass through errno. */
+
+ /* Seek to the new position. */
+ curr_pos = llseek(fd, offset, SEEK_SET);
+ if (curr_pos == -1) {
+ old_errno = errno;
+
+ /* Failed. Try to seek back to the original position. */
+ llseek(fd, start_pos, SEEK_SET);
+
+ errno = old_errno;
+ return(-1);
+ }
+
+ /* Write the data. */
+ ret = write(fd, buf, nbyte);
+ if (ret < 0) {
+ old_errno = errno;
+
+ /* Failed. Try to seek back to the original position. */
+ llseek(fd, start_pos, SEEK_SET);
+
+ errno = old_errno;
+ return(-1);
+ }
+
+ /* Seek back to the start. */
+ curr_pos = llseek(fd, start_pos, SEEK_SET);
+ if (curr_pos == -1)
+ return(-1); /* Pass through errno. */
+
+ return(ret);
+ }
*** /dev/null Sun Mar 9 16:48:31 2003
--- src/libc/posix/unistd/pwrite.txh Fri Mar 7 13:03:02 2003
***************
*** 0 ****
--- 1,53 ----
+ @node pwrite, io
+ @findex pwrite
+ @subheading Syntax
+
+ @example
+ #include <unistd.h>
+
+ int pwrite(int file, const void *buffer, size_t count, off_t offset);
+ @end example
+
+ @subheading Description
+
+ This function writes @var{count} bytes from @var{buffer} to
+ @var{file} at position @var{offset}. It returns the number of bytes
+ actually written. It will return zero or a number less than
+ @var{count} if the disk is full, and may return less than @var{count}
+ even under valid conditions.
+
+ Note that if @var{file} is a text file, @code{pwrite} may write more
+ bytes than it reports.
+
+ If @var{count} is zero, the function does nothing and returns zero.
+ Use @code{_write} if you want to actually ask DOS to write zero bytes.
+
+ The precise behavior of @code{pwrite} when the target filesystem is full
+ are somewhat troublesome, because DOS doesn't fail the underlying system
+ call. If your application needs to rely on @code{errno} being set to
+ @code{ENOSPC} in such cases, you need to invoke @code{pwrite} as shown in
+ an example for @code{write} (@pxref{write}). In a nutshell, the trick is
+ to call @code{pwrite} one more time after it returns a value smaller
+ than the @var{count} parameter; then it will @emph{always} set @code{errno}
+ if the disk is full.
+
+ @subheading Return Value
+
+ The number of bytes written, zero at EOF, or -1 on error.
+
+ @subheading Portability
+
+ @portability !ansi, !posix-1003.2-1992, posix-1003.1-2001
+
+ @subheading Example
+
+ @example
+ const char buf[] = "abc";
+ const size_t bufsize = strlen(buf);
+
+ /* Write out buf, then overwrite 'b' with 'd'. NB: We should check
+ * for errors. */
+ lseek(fd, 0L, SEEK_SET);
+ write(fd, buf, bufsize);
+ pwrite(fd, "d", 1, 1);
+ @end example
*** /dev/null Sun Mar 9 16:48:32 2003
--- tests/libc/posix/unistd/t-lseek.c Fri Mar 7 14:19:02 2003
***************
*** 0 ****
--- 1,81 ----
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
+
+ #define TEST_FILE "t-lseek.tst"
+
+ int
+ main (int argc, char *argv[])
+ {
+ int fd;
+ off_t o;
+ int ret;
+
+ fd = open(TEST_FILE, O_RDWR|O_TRUNC|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR);
+ if (fd < 0)
+ {
+ puts("Unable to create test file '" TEST_FILE "'!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = write(fd, "a", 1);
+ if (ret < 0)
+ {
+ puts("write() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ o = lseek(fd, 1024 * 1024, SEEK_SET);
+ if (ret < 0)
+ {
+ puts("lseek() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = write(fd, "b", 1);
+ if (ret < 0)
+ {
+ puts("write() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ o = lseek(fd, 2 * 1024 * 1024, SEEK_SET);
+ if (ret < 0)
+ {
+ puts("lseek() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = write(fd, "c", 1);
+ if (ret < 0)
+ {
+ puts("write() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = close(fd);
+ if (ret < 0)
+ {
+ puts("close() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ puts("PASS");
+ return(EXIT_SUCCESS);
+ }
*** /dev/null Sun Mar 9 16:48:32 2003
--- tests/libc/posix/unistd/t-pwrite.c Sat Mar 8 11:44:58 2003
***************
*** 0 ****
--- 1,148 ----
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <io.h>
+ #include <libc/fd_props.h>
+
+ #define TEST_FILE "t-pwrite.tst"
+ #define EXTEND_LENGTH (1024 * 1024)
+
+ int
+ main (int argc, char *argv[])
+ {
+ int fd;
+ int ret;
+ const char orig_buf[] = "abc";
+ const size_t orig_bufsize = strlen(orig_buf);
+ const char repl_char[] = "d"; /* Replacement character */
+ const size_t repl_pos = 1; /* Replacement position */
+ char after_buf[] = "XXX";
+ char buf[128];
+ const size_t bufsize = sizeof(buf);
+ const int fd_stdout = fileno(stdout);
+ const int fd_stderr = fileno(stderr);
+ const char msg_stdout[] = "Just a test (stdout)\n";
+ const char msg_stderr[] = "Just a test (stderr)\n";
+
+ /* Test overwriting a particular position. */
+ strcpy(after_buf, orig_buf);
+ after_buf[repl_pos] = repl_char[0];
+
+ fd = open(TEST_FILE, O_RDWR|O_TRUNC|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR);
+ if (fd < 0)
+ {
+ puts("Unable to create test file '" TEST_FILE "'!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = write(fd, orig_buf, orig_bufsize);
+ if (ret < 0)
+ {
+ puts("write() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = pwrite(fd, repl_char, 1, repl_pos);
+ if (ret < 0)
+ {
+ puts("pwrite() to overwrite failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ /* Check that the file now contains after_buf. */
+ ret = lseek(fd, 0, SEEK_SET);
+ if (ret < 0)
+ {
+ puts("lseek() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = read(fd, buf, bufsize);
+ if (ret < 0)
+ {
+ puts("read() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ buf[sizeof(buf) - 1] = '\0';
+
+ if (strncmp(after_buf, buf, strlen(after_buf)) != 0)
+ {
+ puts("Data comparison failed!");
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ /* Try extending the file's size. */
+ ret = pwrite(fd, orig_buf, orig_bufsize, EXTEND_LENGTH);
+ if (ret < 0)
+ {
+ puts("pwrite() to extend failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ /* Check the file size. */
+ ret = filelength(fd);
+ if (ret < 0)
+ {
+ puts("filelength() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ if (ret != (EXTEND_LENGTH + orig_bufsize))
+ {
+ puts("Failed to extend file to correct length!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = close(fd);
+ if (ret < 0)
+ {
+ puts("close() failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ /* Try writing to stdout, stderr. */
+ ret = pwrite(fd_stdout, msg_stdout, strlen(msg_stdout), 1024);
+ if (ret < 0)
+ {
+ puts("pwrite() to stdout failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ ret = pwrite(fd_stderr, msg_stderr, strlen(msg_stderr), 1024);
+ if (ret < 0)
+ {
+ puts("pwrite() to stderr failed!");
+ perror(argv[0]);
+ puts("FAIL");
+ return(EXIT_FAILURE);
+ }
+
+ puts("PASS");
+ return(EXIT_SUCCESS);
+ }
- Raw text -