X-Git-Url: http://git.hcoop.net/bpt/guile.git/blobdiff_plain/fc9c5d0684420f55858ce28e54d85e1eb4fdbde0..4d3406a84750589ffa70669bb923343082efaeb5:/libguile/fports.c diff --git a/libguile/fports.c b/libguile/fports.c index 8baeb6826..5d374950f 100644 --- a/libguile/fports.c +++ b/libguile/fports.c @@ -1,23 +1,26 @@ -/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA */ -#if HAVE_CONFIG_H +#define _LARGEFILE64_SOURCE /* ask for stat64 etc */ + +#ifdef HAVE_CONFIG_H # include #endif @@ -29,6 +32,7 @@ #include "libguile/gc.h" #include "libguile/posix.h" #include "libguile/dynwind.h" +#include "libguile/hashtab.h" #include "libguile/fports.h" @@ -37,8 +41,6 @@ #endif #ifdef HAVE_UNISTD_H #include -#else -size_t fwrite (); #endif #ifdef HAVE_IO_H #include @@ -48,6 +50,7 @@ size_t fwrite (); #endif #include +#include #include "libguile/iselect.h" @@ -55,9 +58,35 @@ size_t fwrite (); #ifdef __MINGW32__ # include # include -# define ftruncate(fd, size) chsize (fd, size) #endif /* __MINGW32__ */ +#include + +/* Mingw (version 3.4.5, circa 2006) has ftruncate as an alias for chsize + already, but have this code here in case that wasn't so in past versions, + or perhaps to help other minimal DOS environments. + + gnulib ftruncate.c has code using fcntl F_CHSIZE and F_FREESP, which + might be possibilities if we've got other systems without ftruncate. */ + +#if HAVE_CHSIZE && ! HAVE_FTRUNCATE +# define ftruncate(fd, size) chsize (fd, size) +#undef HAVE_FTRUNCATE +#define HAVE_FTRUNCATE 1 +#endif + +#if SIZEOF_OFF_T == SIZEOF_INT +#define OFF_T_MAX INT_MAX +#define OFF_T_MIN INT_MIN +#elif SIZEOF_OFF_T == SIZEOF_LONG +#define OFF_T_MAX LONG_MAX +#define OFF_T_MIN LONG_MIN +#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG +#define OFF_T_MAX LONG_LONG_MAX +#define OFF_T_MIN LONG_LONG_MIN +#else +#error Oops, unknown OFF_T size +#endif scm_t_bits scm_tc16_fport; @@ -93,7 +122,7 @@ scm_fport_buffer_add (SCM port, long read_size, int write_size) if (SCM_INPUT_PORT_P (port) && read_size > 0) { - pt->read_buf = scm_gc_malloc (read_size, "port buffer"); + pt->read_buf = scm_gc_malloc_pointerless (read_size, "port buffer"); pt->read_pos = pt->read_end = pt->read_buf; pt->read_buf_size = read_size; } @@ -105,7 +134,7 @@ scm_fport_buffer_add (SCM port, long read_size, int write_size) if (SCM_OUTPUT_PORT_P (port) && write_size > 0) { - pt->write_buf = scm_gc_malloc (write_size, "port buffer"); + pt->write_buf = scm_gc_malloc_pointerless (write_size, "port buffer"); pt->write_pos = pt->write_buf; pt->write_buf_size = write_size; } @@ -155,7 +184,7 @@ SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0, } else { - SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) ^ SCM_BUFLINE); + SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) & ~(scm_t_bits)SCM_BUFLINE); } if (SCM_UNBNDP (size)) @@ -195,33 +224,35 @@ SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0, /* Move ports with the specified file descriptor to new descriptors, * resetting the revealed count to 0. */ - -void -scm_evict_ports (int fd) +static void +scm_i_evict_port (void *closure, SCM port) { - long i; - - scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex); + int fd = * (int*) closure; - for (i = 0; i < scm_i_port_table_size; i++) + if (SCM_FPORTP (port)) { - SCM port = scm_i_port_table[i]->port; + scm_t_port *p; + scm_t_fport *fp; - if (SCM_FPORTP (port)) - { - scm_t_fport *fp = SCM_FSTREAM (port); + /* XXX: In some cases, we can encounter a port with no associated ptab + entry. */ + p = SCM_PTAB_ENTRY (port); + fp = (p != NULL) ? (scm_t_fport *) p->stream : NULL; - if (fp->fdes == fd) - { - fp->fdes = dup (fd); - if (fp->fdes == -1) - scm_syserror ("scm_evict_ports"); - scm_set_port_revealed_x (port, scm_from_int (0)); - } + if ((fp != NULL) && (fp->fdes == fd)) + { + fp->fdes = dup (fd); + if (fp->fdes == -1) + scm_syserror ("scm_evict_ports"); + scm_set_port_revealed_x (port, scm_from_int (0)); } } +} - scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex); +void +scm_evict_ports (int fd) +{ + scm_c_port_for_each (scm_i_evict_port, (void *) &fd); } @@ -293,13 +324,13 @@ SCM_DEFINE (scm_open_file, "open-file", 2, 0, 0, char *md; char *ptr; - scm_frame_begin (0); + scm_dynwind_begin (0); file = scm_to_locale_string (filename); - scm_frame_free (file); + scm_dynwind_free (file); md = scm_to_locale_string (mode); - scm_frame_free (md); + scm_dynwind_free (md); switch (*md) { @@ -336,7 +367,7 @@ SCM_DEFINE (scm_open_file, "open-file", 2, 0, 0, } ptr++; } - SCM_SYSCALL (fdes = open (file, flags, 0666)); + SCM_SYSCALL (fdes = open_or_open64 (file, flags, 0666)); if (fdes == -1) { int en = errno; @@ -347,7 +378,7 @@ SCM_DEFINE (scm_open_file, "open-file", 2, 0, 0, } port = scm_i_fdes_to_port (fdes, scm_i_mode_bits (mode), filename); - scm_frame_end (); + scm_dynwind_end (); return port; } @@ -434,7 +465,8 @@ scm_i_fdes_to_port (int fdes, long mode_bits, SCM name) pt = SCM_PTAB_ENTRY(port); { scm_t_fport *fp - = (scm_t_fport *) scm_gc_malloc (sizeof (scm_t_fport), "file port"); + = (scm_t_fport *) scm_gc_malloc_pointerless (sizeof (scm_t_fport), + "file port"); fp->fdes = fdes; pt->rw_random = SCM_FDES_RANDOM_P (fdes); @@ -460,9 +492,8 @@ scm_fdes_to_port (int fdes, char *mode, SCM name) static int fport_input_waiting (SCM port) { - int fdes = SCM_FSTREAM (port)->fdes; - #ifdef HAVE_SELECT + int fdes = SCM_FSTREAM (port)->fdes; struct timeval timeout; SELECT_TYPE read_set; SELECT_TYPE write_set; @@ -482,10 +513,15 @@ fport_input_waiting (SCM port) < 0) scm_syserror ("fport_input_waiting"); return FD_ISSET (fdes, &read_set) ? 1 : 0; -#elif defined (FIONREAD) + +#elif HAVE_IOCTL && defined (FIONREAD) + /* Note: cannot test just defined(FIONREAD) here, since mingw has FIONREAD + (for use with winsock ioctlsocket()) but not ioctl(). */ + int fdes = SCM_FSTREAM (port)->fdes; int remir; ioctl(fdes, FIONREAD, &remir); return remir; + #else scm_misc_error ("fport_input_waiting", "Not fully implemented on this platform", @@ -558,7 +594,7 @@ static void fport_flush (SCM port); /* fill a port's read-buffer with a single read. returns the first char or EOF if end of file. */ -static int +static scm_t_wchar fport_fill_input (SCM port) { long count; @@ -572,7 +608,7 @@ fport_fill_input (SCM port) if (count == -1) scm_syserror ("fport_fill_input"); if (count == 0) - return EOF; + return (scm_t_wchar) EOF; else { pt->read_pos = pt->read_buf; @@ -581,25 +617,25 @@ fport_fill_input (SCM port) } } -static off_t -fport_seek (SCM port, off_t offset, int whence) +static scm_t_off +fport_seek (SCM port, scm_t_off offset, int whence) { scm_t_port *pt = SCM_PTAB_ENTRY (port); scm_t_fport *fp = SCM_FSTREAM (port); - off_t rv; - off_t result; + off_t_or_off64_t rv; + off_t_or_off64_t result; if (pt->rw_active == SCM_PORT_WRITE) { if (offset != 0 || whence != SEEK_CUR) { fport_flush (port); - result = rv = lseek (fp->fdes, offset, whence); + result = rv = lseek_or_lseek64 (fp->fdes, offset, whence); } else { /* read current position without disturbing the buffer. */ - rv = lseek (fp->fdes, offset, whence); + rv = lseek_or_lseek64 (fp->fdes, offset, whence); result = rv + (pt->write_pos - pt->write_buf); } } @@ -609,13 +645,13 @@ fport_seek (SCM port, off_t offset, int whence) { /* could expand to avoid a second seek. */ scm_end_input (port); - result = rv = lseek (fp->fdes, offset, whence); + result = rv = lseek_or_lseek64 (fp->fdes, offset, whence); } else { /* read current position without disturbing the buffer (particularly the unread-char buffer). */ - rv = lseek (fp->fdes, offset, whence); + rv = lseek_or_lseek64 (fp->fdes, offset, whence); result = rv - (pt->read_end - pt->read_pos); if (pt->read_buf == pt->putback_buf) @@ -624,7 +660,7 @@ fport_seek (SCM port, off_t offset, int whence) } else /* SCM_PORT_NEITHER */ { - result = rv = lseek (fp->fdes, offset, whence); + result = rv = lseek_or_lseek64 (fp->fdes, offset, whence); } if (rv == -1) @@ -634,7 +670,7 @@ fport_seek (SCM port, off_t offset, int whence) } static void -fport_truncate (SCM port, off_t length) +fport_truncate (SCM port, scm_t_off length) { scm_t_fport *fp = SCM_FSTREAM (port); @@ -679,7 +715,7 @@ fport_write (SCM port, const void *data, size_t size) } { - off_t space = pt->write_end - pt->write_pos; + scm_t_off space = pt->write_end - pt->write_pos; if (size <= space) { @@ -760,9 +796,9 @@ fport_flush (SCM port) const char *msg = "Error: could not flush file-descriptor "; char buf[11]; - write (2, msg, strlen (msg)); + full_write (2, msg, strlen (msg)); sprintf (buf, "%d\n", fp->fdes); - write (2, buf, strlen (buf)); + full_write (2, buf, strlen (buf)); count = remaining; }