Commit e070fdea authored by Ron Steinke's avatar Ron Steinke

Modified Files: glib/ChangeLog glib/glib.def glib/glib/giochannel.c

     Modified Files:
 	glib/ChangeLog glib/glib.def glib/glib/giochannel.c
 	glib/glib/giochannel.h glib/glib/giounix.c
 	glib/glib/giowin32.c
 	glib/docs/reference/glib/glib-sections.txt
 	glib/tests/iochannel-test.c glib/tests/unicode-collate.c
 	glib/tests/unicode-normalize.c
     Added Files:
 	glib/tests/iochannel-test-infile

        * glib/giochannel.c: API changes, fixes to
        error handling, some internal restructuring
        * glib/giochannel.h: API changes, documentation for
        elements in GIOChannel structure
        * glib/giounix.c: Matched API changes, implemented
        backend to set is_readable, is_writeable, is_seekable
        flags, added a test to catch large values of count
        for which the behavior of write() is undefined
        * glib/giowin32.c: Changed to match new prototypes for
        io_close() and io_seek(), removed references to
        G_IO_STATUS_INTR, set is_seekable flag in channel
        creation functions
        * glib.def: Renamed g_channel_error_quark() and
        g_channel_error_from_errno() to g_io_channel_error_quark() and
        g_io_channel_error_from_errno(); added new functions
        g_io_channel_get_buffered() and g_io_channel_set_buffered()
        * docs/reference/glib/glib-sections.txt: Modified iochannel
        section to reflect new functions and API changes
        * tests/iochannel-test.c: Fixed to work with API changes
        * tests/iochannel-test-infile: New file; input file
        for iochannel-test
        * tests/unicode-collate.c tests/unicode-normalize.c:
        Changed G_IO_FILE_MODE_READ to "r" to match API change
parent c71a77a5
Fri Jul 20 19:19:10 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* glib/giochannel.c: API changes, fixes to
error handling, some internal restructuring
* glib/giochannel.h: API changes, documentation for
elements in GIOChannel structure
* glib/giounix.c: Matched API changes, implemented
backend to set is_readable, is_writeable, is_seekable
flags, added a test to catch large values of count
for which the behavior of write() is undefined
* glib/giowin32.c: Changed to match new prototypes for
io_close() and io_seek(), removed references to
G_IO_STATUS_INTR, set is_seekable flag in channel
creation functions
* glib.def: Renamed g_channel_error_quark() and
g_channel_error_from_errno() to g_io_channel_error_quark() and
g_io_channel_error_from_errno(); added new functions
g_io_channel_get_buffered() and g_io_channel_set_buffered()
* docs/reference/glib/glib-sections.txt: Modified iochannel
section to reflect new functions and API changes
* tests/iochannel-test.c: Fixed to work with API changes
* tests/iochannel-test-infile: New file; input file
for iochannel-test
* tests/unicode-collate.c tests/unicode-normalize.c:
Changed G_IO_FILE_MODE_READ to "r" to match API change
Fri Jul 20 19:16:24 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* gobject/glib-genmarshal.c: modified to create header files
......
Fri Jul 20 19:19:10 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* glib/giochannel.c: API changes, fixes to
error handling, some internal restructuring
* glib/giochannel.h: API changes, documentation for
elements in GIOChannel structure
* glib/giounix.c: Matched API changes, implemented
backend to set is_readable, is_writeable, is_seekable
flags, added a test to catch large values of count
for which the behavior of write() is undefined
* glib/giowin32.c: Changed to match new prototypes for
io_close() and io_seek(), removed references to
G_IO_STATUS_INTR, set is_seekable flag in channel
creation functions
* glib.def: Renamed g_channel_error_quark() and
g_channel_error_from_errno() to g_io_channel_error_quark() and
g_io_channel_error_from_errno(); added new functions
g_io_channel_get_buffered() and g_io_channel_set_buffered()
* docs/reference/glib/glib-sections.txt: Modified iochannel
section to reflect new functions and API changes
* tests/iochannel-test.c: Fixed to work with API changes
* tests/iochannel-test-infile: New file; input file
for iochannel-test
* tests/unicode-collate.c tests/unicode-normalize.c:
Changed G_IO_FILE_MODE_READ to "r" to match API change
Fri Jul 20 19:16:24 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* gobject/glib-genmarshal.c: modified to create header files
......
Fri Jul 20 19:19:10 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* glib/giochannel.c: API changes, fixes to
error handling, some internal restructuring
* glib/giochannel.h: API changes, documentation for
elements in GIOChannel structure
* glib/giounix.c: Matched API changes, implemented
backend to set is_readable, is_writeable, is_seekable
flags, added a test to catch large values of count
for which the behavior of write() is undefined
* glib/giowin32.c: Changed to match new prototypes for
io_close() and io_seek(), removed references to
G_IO_STATUS_INTR, set is_seekable flag in channel
creation functions
* glib.def: Renamed g_channel_error_quark() and
g_channel_error_from_errno() to g_io_channel_error_quark() and
g_io_channel_error_from_errno(); added new functions
g_io_channel_get_buffered() and g_io_channel_set_buffered()
* docs/reference/glib/glib-sections.txt: Modified iochannel
section to reflect new functions and API changes
* tests/iochannel-test.c: Fixed to work with API changes
* tests/iochannel-test-infile: New file; input file
for iochannel-test
* tests/unicode-collate.c tests/unicode-normalize.c:
Changed G_IO_FILE_MODE_READ to "r" to match API change
Fri Jul 20 19:16:24 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* gobject/glib-genmarshal.c: modified to create header files
......
Fri Jul 20 19:19:10 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* glib/giochannel.c: API changes, fixes to
error handling, some internal restructuring
* glib/giochannel.h: API changes, documentation for
elements in GIOChannel structure
* glib/giounix.c: Matched API changes, implemented
backend to set is_readable, is_writeable, is_seekable
flags, added a test to catch large values of count
for which the behavior of write() is undefined
* glib/giowin32.c: Changed to match new prototypes for
io_close() and io_seek(), removed references to
G_IO_STATUS_INTR, set is_seekable flag in channel
creation functions
* glib.def: Renamed g_channel_error_quark() and
g_channel_error_from_errno() to g_io_channel_error_quark() and
g_io_channel_error_from_errno(); added new functions
g_io_channel_get_buffered() and g_io_channel_set_buffered()
* docs/reference/glib/glib-sections.txt: Modified iochannel
section to reflect new functions and API changes
* tests/iochannel-test.c: Fixed to work with API changes
* tests/iochannel-test-infile: New file; input file
for iochannel-test
* tests/unicode-collate.c tests/unicode-normalize.c:
Changed G_IO_FILE_MODE_READ to "r" to match API change
Fri Jul 20 19:16:24 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* gobject/glib-genmarshal.c: modified to create header files
......
Fri Jul 20 19:19:10 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* glib/giochannel.c: API changes, fixes to
error handling, some internal restructuring
* glib/giochannel.h: API changes, documentation for
elements in GIOChannel structure
* glib/giounix.c: Matched API changes, implemented
backend to set is_readable, is_writeable, is_seekable
flags, added a test to catch large values of count
for which the behavior of write() is undefined
* glib/giowin32.c: Changed to match new prototypes for
io_close() and io_seek(), removed references to
G_IO_STATUS_INTR, set is_seekable flag in channel
creation functions
* glib.def: Renamed g_channel_error_quark() and
g_channel_error_from_errno() to g_io_channel_error_quark() and
g_io_channel_error_from_errno(); added new functions
g_io_channel_get_buffered() and g_io_channel_set_buffered()
* docs/reference/glib/glib-sections.txt: Modified iochannel
section to reflect new functions and API changes
* tests/iochannel-test.c: Fixed to work with API changes
* tests/iochannel-test-infile: New file; input file
for iochannel-test
* tests/unicode-collate.c tests/unicode-normalize.c:
Changed G_IO_FILE_MODE_READ to "r" to match API change
Fri Jul 20 19:16:24 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* gobject/glib-genmarshal.c: modified to create header files
......
Fri Jul 20 19:19:10 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* glib/giochannel.c: API changes, fixes to
error handling, some internal restructuring
* glib/giochannel.h: API changes, documentation for
elements in GIOChannel structure
* glib/giounix.c: Matched API changes, implemented
backend to set is_readable, is_writeable, is_seekable
flags, added a test to catch large values of count
for which the behavior of write() is undefined
* glib/giowin32.c: Changed to match new prototypes for
io_close() and io_seek(), removed references to
G_IO_STATUS_INTR, set is_seekable flag in channel
creation functions
* glib.def: Renamed g_channel_error_quark() and
g_channel_error_from_errno() to g_io_channel_error_quark() and
g_io_channel_error_from_errno(); added new functions
g_io_channel_get_buffered() and g_io_channel_set_buffered()
* docs/reference/glib/glib-sections.txt: Modified iochannel
section to reflect new functions and API changes
* tests/iochannel-test.c: Fixed to work with API changes
* tests/iochannel-test-infile: New file; input file
for iochannel-test
* tests/unicode-collate.c tests/unicode-normalize.c:
Changed G_IO_FILE_MODE_READ to "r" to match API change
Fri Jul 20 19:16:24 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* gobject/glib-genmarshal.c: modified to create header files
......
Fri Jul 20 19:19:10 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* glib/giochannel.c: API changes, fixes to
error handling, some internal restructuring
* glib/giochannel.h: API changes, documentation for
elements in GIOChannel structure
* glib/giounix.c: Matched API changes, implemented
backend to set is_readable, is_writeable, is_seekable
flags, added a test to catch large values of count
for which the behavior of write() is undefined
* glib/giowin32.c: Changed to match new prototypes for
io_close() and io_seek(), removed references to
G_IO_STATUS_INTR, set is_seekable flag in channel
creation functions
* glib.def: Renamed g_channel_error_quark() and
g_channel_error_from_errno() to g_io_channel_error_quark() and
g_io_channel_error_from_errno(); added new functions
g_io_channel_get_buffered() and g_io_channel_set_buffered()
* docs/reference/glib/glib-sections.txt: Modified iochannel
section to reflect new functions and API changes
* tests/iochannel-test.c: Fixed to work with API changes
* tests/iochannel-test-infile: New file; input file
for iochannel-test
* tests/unicode-collate.c tests/unicode-normalize.c:
Changed G_IO_FILE_MODE_READ to "r" to match API change
Fri Jul 20 19:16:24 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* gobject/glib-genmarshal.c: modified to create header files
......
Fri Jul 20 19:19:10 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* glib/giochannel.c: API changes, fixes to
error handling, some internal restructuring
* glib/giochannel.h: API changes, documentation for
elements in GIOChannel structure
* glib/giounix.c: Matched API changes, implemented
backend to set is_readable, is_writeable, is_seekable
flags, added a test to catch large values of count
for which the behavior of write() is undefined
* glib/giowin32.c: Changed to match new prototypes for
io_close() and io_seek(), removed references to
G_IO_STATUS_INTR, set is_seekable flag in channel
creation functions
* glib.def: Renamed g_channel_error_quark() and
g_channel_error_from_errno() to g_io_channel_error_quark() and
g_io_channel_error_from_errno(); added new functions
g_io_channel_get_buffered() and g_io_channel_set_buffered()
* docs/reference/glib/glib-sections.txt: Modified iochannel
section to reflect new functions and API changes
* tests/iochannel-test.c: Fixed to work with API changes
* tests/iochannel-test-infile: New file; input file
for iochannel-test
* tests/unicode-collate.c tests/unicode-normalize.c:
Changed G_IO_FILE_MODE_READ to "r" to match API change
Fri Jul 20 19:16:24 (UTC) 2001 Ron Steinke <rsteinke@w-link.net>
* gobject/glib-genmarshal.c: modified to create header files
......
......@@ -594,7 +594,6 @@ g_io_channel_init
<SUBSECTION>
g_io_channel_new_file
GIOFileMode
g_io_channel_read_chars
g_io_channel_read_line
g_io_channel_read_line_string
......@@ -603,14 +602,14 @@ g_io_channel_write_chars
g_io_channel_flush
g_io_channel_seek_position
GSeekType
g_io_channel_close
g_io_channel_shutdown
<SUBSECTION>
GChannelStatus
GChannelError
G_CHANNEL_ERROR
g_channel_error_quark
g_channel_error_from_errno
GIOStatus
GIOChannelError
G_IO_CHANNEL_ERROR
g_io_channel_error_quark
g_io_channel_error_from_errno
<SUBSECTION>
g_io_channel_ref
......@@ -638,10 +637,10 @@ g_io_channel_set_line_term
G_IO_CHANNEL_UNIX_LINE_TERM
G_IO_CHANNEL_DOS_LINE_TERM
G_IO_CHANNEL_MACINTOSH_LINE_TERM
G_IO_CHANNEL_DEFAULT_LINE_TERM
g_io_channel_get_buffered
g_io_channel_set_buffered
g_io_channel_get_encoding
g_io_channel_set_encoding
G_IO_CHANNEL_ENCODE_RAW
<SUBSECTION Private>
g_io_channel_win32_new_fd
......@@ -656,6 +655,7 @@ g_io_channel_read
GIOError
g_io_channel_write
g_io_channel_seek
g_io_channel_close
</SECTION>
<SECTION>
......
......@@ -51,8 +51,6 @@ EXPORTS
g_cache_new
g_cache_remove
g_cache_value_foreach
g_channel_error_quark
g_channel_error_from_errno
g_clear_error
g_completion_add_items
g_completion_clear_items
......@@ -186,9 +184,12 @@ EXPORTS
g_io_add_watch
g_io_add_watch_full
g_io_channel_close
g_io_channel_error_from_errno
g_io_channel_error_quark
g_io_channel_flush
g_io_channel_get_buffer_condition
g_io_channel_get_buffer_size
g_io_channel_get_buffered
g_io_channel_get_encoding
g_io_channel_get_flags
g_io_channel_get_line_term
......@@ -203,6 +204,7 @@ EXPORTS
g_io_channel_seek
g_io_channel_seek_position
g_io_channel_set_buffer_size
g_io_channel_set_buffered
g_io_channel_set_encoding
g_io_channel_set_flags
g_io_channel_set_line_term
......
This diff is collapsed.
......@@ -47,26 +47,22 @@ typedef enum
G_IO_ERROR_UNKNOWN
} GIOError;
#define G_IO_CHANNEL_ERROR g_channel_error_quark()
#define G_IO_CHANNEL_ERROR g_io_channel_error_quark()
typedef enum
{
/* Derived from errno */
G_IO_CHANNEL_ERROR_ACCES,
G_IO_CHANNEL_ERROR_BADF,
G_IO_CHANNEL_ERROR_DEADLK,
G_IO_CHANNEL_ERROR_FAULT,
G_IO_CHANNEL_ERROR_FBIG,
G_IO_CHANNEL_ERROR_INVAL,
G_IO_CHANNEL_ERROR_IO,
G_IO_CHANNEL_ERROR_ISDIR,
G_IO_CHANNEL_ERROR_MFILE,
G_IO_CHANNEL_ERROR_NOLCK,
G_IO_CHANNEL_ERROR_NOSPC,
G_IO_CHANNEL_ERROR_PERM,
G_IO_CHANNEL_ERROR_NXIO,
G_IO_CHANNEL_ERROR_OVERFLOW,
G_IO_CHANNEL_ERROR_PIPE,
G_IO_CHANNEL_ERROR_SPIPE,
/* Other */
G_IO_CHANNEL_ERROR_ENCODE_RW,
G_IO_CHANNEL_ERROR_PCHAR_FLUSH,
/* Unconverted partial UTF-8 chars in buffer during flush */
G_IO_CHANNEL_ERROR_FAILED
} GIOChannelError;
......@@ -75,7 +71,6 @@ typedef enum
G_IO_STATUS_ERROR,
G_IO_STATUS_NORMAL,
G_IO_STATUS_EOF,
G_IO_STATUS_PARTIAL_CHARS, /* like EOF, but with unconverted data left */
G_IO_STATUS_AGAIN
} GIOStatus;
......@@ -99,7 +94,6 @@ typedef enum
#define G_IO_CHANNEL_UNIX_LINE_TERM "\n"
#define G_IO_CHANNEL_DOS_LINE_TERM "\r\n"
#define G_IO_CHANNEL_MACINTOSH_LINE_TERM "\r"
#define G_IO_CHANNEL_ENCODE_RAW "GIOChannelEncodeRaw"
typedef enum
{
......@@ -113,41 +107,30 @@ typedef enum
G_IO_FLAG_SET_MASK = G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK,
} GIOFlags;
typedef enum
{
G_IO_FILE_MODE_READ,
G_IO_FILE_MODE_WRITE,
G_IO_FILE_MODE_APPEND,
G_IO_FILE_MODE_READ_WRITE,
G_IO_FILE_MODE_READ_WRITE_TRUNCATE,
G_IO_FILE_MODE_READ_WRITE_APPEND,
} GIOFileMode;
struct _GIOChannel
{
guint channel_flags;
guint ref_count;
GIOFuncs *funcs;
gchar *encoding;
GIConv read_cd;
GIConv write_cd;
gchar *line_term;
gchar *line_term; /* String which indicates the end of a line of text */
gsize buf_size;
GString *read_buf;
GString *encoded_read_buf;
GString *write_buf;
/* Group the flags together to save memory */
gboolean use_buffer : 1;
gboolean do_encode : 1;
gboolean ready_to_read : 1;
gboolean ready_to_write : 1;
gboolean close_on_unref : 1;
gboolean seekable_cached : 1;
gboolean is_seekable : 1;
GString *read_buf; /* Raw data from the channel */
GString *encoded_read_buf; /* Channel data converted to UTF-8 */
GString *write_buf; /* Data ready to be written to the file */
gchar partial_write_buf[6]; /* UTF-8 partial characters, null terminated */
/* Group the flags together, immediately after partial_write_buf, to save memory */
gboolean use_buffer : 1; /* The encoding uses the buffers */
gboolean do_encode : 1; /* The encoding uses the GIConv coverters */
gboolean close_on_unref : 1; /* Close the channel on final unref */
gboolean is_readable : 1; /* Cached GIOFlag */
gboolean is_writeable : 1; /* ditto */
gboolean is_seekable : 1; /* ditto */
};
typedef gboolean (*GIOFunc) (GIOChannel *source,
......@@ -229,6 +212,9 @@ GIOFlags g_io_channel_get_flags (GIOChannel *channel);
void g_io_channel_set_line_term (GIOChannel *channel,
const gchar *line_term);
G_CONST_RETURN gchar* g_io_channel_get_line_term (GIOChannel *channel);
void g_io_channel_set_buffered (GIOChannel *channel,
gboolean buffered);
gboolean g_io_channel_get_buffered (GIOChannel *channel);
GIOStatus g_io_channel_set_encoding (GIOChannel *channel,
const gchar *encoding,
GError **error);
......@@ -265,13 +251,13 @@ GIOStatus g_io_channel_seek_position (GIOChannel *channel,
GSeekType type,
GError **error);
GIOChannel* g_io_channel_new_file (const gchar *filename,
GIOFileMode mode,
const gchar *mode,
GError **error);
/* Error handling */
GQuark g_channel_error_quark (void);
GIOChannelError g_channel_error_from_errno (gint en);
GQuark g_io_channel_error_quark (void);
GIOChannelError g_io_channel_error_from_errno (gint en);
/* On Unix, IO channels created with this function for any file
* descriptor or socket.
......
......@@ -177,6 +177,9 @@ g_io_unix_read (GIOChannel *channel,
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
gssize result;
if (count > SSIZE_MAX) /* At least according to the Debian manpage for read */
count = SSIZE_MAX;
retry:
result = read (unix_channel->fd, buf, count);
......@@ -196,7 +199,7 @@ g_io_unix_read (GIOChannel *channel,
#endif
default:
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
g_io_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
......@@ -236,7 +239,7 @@ g_io_unix_write (GIOChannel *channel,
#endif
default:
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
g_io_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
......@@ -278,7 +281,7 @@ g_io_unix_seek (GIOChannel *channel,
if (result < 0)
{
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
g_io_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
......@@ -296,7 +299,7 @@ g_io_unix_close (GIOChannel *channel,
if (close (unix_channel->fd) < 0)
{
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
g_io_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
......@@ -351,19 +354,6 @@ static const glong g_io_unix_fcntl_posix_flags[] = {
};
#define G_IO_UNIX_NUM_FCNTL_FLAGS G_N_ELEMENTS (g_io_unix_fcntl_flags)
static const GIOFlags g_io_unix_fcntl_flags_read_only[] = {
G_IO_FLAG_IS_READABLE,
G_IO_FLAG_IS_WRITEABLE,
};
static const glong g_io_unix_fcntl_posix_flags_read_only[] = {
O_RDONLY | O_RDWR,
O_WRONLY | O_RDWR,
};
/* Only need to map posix_flags -> flags for read only, not the
* other way around, so this works.
*/
#define G_IO_UNIX_NUM_FCNTL_FLAGS_READ_ONLY G_N_ELEMENTS (g_io_unix_fcntl_flags_read_only)
static GIOStatus
g_io_unix_set_flags (GIOChannel *channel,
GIOFlags flags,
......@@ -382,7 +372,7 @@ g_io_unix_set_flags (GIOChannel *channel,
if (fcntl (unix_channel->fd, F_SETFL, fcntl_flags) == -1)
{
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
g_io_channel_error_from_errno (errno),
g_strerror (errno));
return G_IO_STATUS_ERROR;
}
......@@ -397,103 +387,200 @@ g_io_unix_get_flags (GIOChannel *channel)
glong fcntl_flags;
gint loop;
GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
struct stat buffer;
fcntl_flags = fcntl (unix_channel->fd, F_GETFL);
if (fcntl_flags == -1)
{
g_warning (G_STRLOC "Error while getting flags for FD: %s (%d)\n",
g_strerror (errno), errno);
return 0;
}
if (!channel->seekable_cached)
{
channel->seekable_cached = TRUE;
/* I'm not sure if fstat on a non-file (e.g., socket) works
* it should be safe to sat if it fails, the fd isn't seekable.
*/
if (fstat (unix_channel->fd, &buffer) == -1 ||
!S_ISREG (buffer.st_mode))
channel->is_seekable = FALSE;
else
channel->is_seekable = TRUE;
}
for (loop = 0; loop < G_IO_UNIX_NUM_FCNTL_FLAGS; loop++)
if (fcntl_flags & g_io_unix_fcntl_posix_flags[loop])
flags |= g_io_unix_fcntl_flags[loop];
for (loop = 0; loop < G_IO_UNIX_NUM_FCNTL_FLAGS_READ_ONLY; loop++)
if (fcntl_flags & g_io_unix_fcntl_posix_flags_read_only[loop])
flags |= g_io_unix_fcntl_flags_read_only[loop];
if (channel->is_seekable)
flags |= G_IO_FLAG_IS_SEEKABLE;
return flags;
}
GIOChannel *
g_io_channel_new_file (const gchar *filename,
GIOFileMode mode,
const gchar *mode,
GError **error)
{
FILE *f;
int fid;
gchar *mode_name;
int fid, flags;
GIOChannel *channel;
enum { /* Cheesy hack */
MODE_R = 1 << 0,
MODE_W = 1 << 1,
MODE_A = 1 << 2,
MODE_PLUS = 1 << 3,
} mode_num;
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (mode != NULL, NULL);
g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
switch (mode[0])
{
case 'r':
mode_num = MODE_R;
break;
case 'w':
mode_num = MODE_W;
break;
case 'a':
mode_num = MODE_A;
break;
default:
g_warning ("Invalid GIOFileMode %s.\n", mode);
return NULL;
}
switch (mode[1])
{
case '\0':
break;
case '+':
if (mode[2] == '\0')
{
mode_num |= MODE_PLUS;
break;
}
/* Fall through */
default:
g_warning ("Invalid GIOFileMode %s.\n", mode);
return NULL;
}
switch (mode)
switch (mode_num)
{
case G_IO_FILE_MODE_READ:
mode_name = "r";
case MODE_R:
flags = O_RDONLY;
break;
case G_IO_FILE_MODE_WRITE:
mode_name = "w";
case MODE_W:
flags = O_WRONLY | O_TRUNC | O_CREAT;
break;
case G_IO_FILE_MODE_APPEND:
mode_name = "a";
case MODE_A:
flags = O_WRONLY | O_APPEND | O_CREAT;
break;
case G_IO_FILE_MODE_READ_WRITE:
mode_name = "r+";
case MODE_R | MODE_PLUS:
flags = O_RDWR;
break;
case G_IO_FILE_MODE_READ_WRITE_TRUNCATE:
mode_name = "w+";
case MODE_W | MODE_PLUS:
flags = O_RDWR | O_TRUNC | O_CREAT;
break;
case G_IO_FILE_MODE_READ_WRITE_APPEND:
mode_name = "a+";
case MODE_A | MODE_PLUS:
flags = O_RDWR | O_APPEND | O_CREAT;
break;
default:
g_warning ("Invalid GIOFileMode %i.\n", mode);
return NULL;
g_assert_not_reached ();
flags = 0;
}
f = fopen (filename, mode_name);
if (!f)
fid = open (filename, flags);
if (fid < 0)
{
g_set_error (error, G_FILE_ERROR,
g_file_error_from_errno (errno),
strerror (errno));
return (GIOChannel *)NULL;
}
fid = fileno (f);
channel = g_io_channel_unix_new (fid);
channel = (GIOChannel *) g_new (GIOUnixChannel, 1);
channel->close_on_unref = TRUE;
channel->is_seekable = TRUE;
switch (mode_num)
{
case MODE_R:
channel->is_readable = TRUE;
channel->is_writeable = FALSE;
break;
case MODE_W:
case MODE_A:
channel->is_readable = FALSE;
channel->is_writeable = TRUE;
break;
case MODE_R | MODE_PLUS:
case MODE_W | MODE_PLUS:
case MODE_A | MODE_PLUS:
channel->is_readable = TRUE;
channel->is_writeable = TRUE;
break;
default:
g_assert_not_reached ();
}
g_io_channel_init (channel);
channel->funcs = &unix_channel_funcs;
((GIOUnixChannel *) channel)->fd = fid;
return channel;
}
GIOChannel *
g_io_channel_unix_new (gint fd)
{
struct stat buffer;
GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
GIOChannel *channel = (GIOChannel *)unix_channel;
int flags;
g_io_channel_init (channel);
channel->funcs = &unix_channel_funcs;
/* I'm not sure if fstat on a non-file (e.g., socket) works
* it should be safe to say if it fails, the fd isn't seekable.
*/
/* Newer UNIX versions support S_ISSOCK(), fstat() will probably
* succeed in most cases.
*/
if (fstat (unix_channel->fd, &buffer) == 0)
channel->is_seekable = S_ISREG (buffer.st_mode) || S_ISCHR (buffer.st_mode)
|| S_ISBLK (buffer.st_mode);
else /* Assume not seekable */
channel->is_seekable = FALSE;
flags = fcntl (fd, F_GETFL);
if (flags != -1)
{
/* Don't know if fcntl flags overlap, be careful */
if (flags & O_WRONLY)
{
channel->is_readable = FALSE;
channel->is_writeable = TRUE;
}
else if (flags & O_RDWR)
channel->is_readable = channel->is_writeable = TRUE;
#if O_RDONLY == 0
else /* O_RDONLY defined as zero on linux (elsewhere?) */
{
channel->is_readable = TRUE;
channel->is_writeable = FALSE;
}
#else /* O_RDONLY == 0 */
else if (flags & O_RDONLY)
{
channel->is_readable = TRUE;
channel->is_writeable = FALSE;
}
else
channel->is_readable = channel->is_writeable = FALSE;
#endif /* O_RDONLY == 0 */
}
else
{
</