summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'io.c')
-rw-r--r--io.c332
1 files changed, 296 insertions, 36 deletions
diff --git a/io.c b/io.c
index 5573e76a64..ac4771eb81 100644
--- a/io.c
+++ b/io.c
@@ -6,7 +6,7 @@
$Date$
created at: Fri Oct 15 18:08:59 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -20,7 +20,7 @@
#if !defined(DJGPP) && !defined(NT) && !defined(__human68k__)
#include <sys/ioctl.h>
#endif
-#if defined(HAVE_FCNTL)
+#if defined(HAVE_FCNTL) || defined(NT)
#include <fcntl.h>
#endif
@@ -54,6 +54,7 @@ struct timeval {
#include <sys/errno.h>
#include <unix.mac.h>
#include <compat.h>
+ extern char* strdup(const char*);
#endif
extern void Init_File _((void));
@@ -99,7 +100,7 @@ static VALUE lineno;
#elif defined(__BEOS__)
# define ReadDataPending(fp) (fp->_state._eof == 0)
#elif defined(USE_CWGUSI)
-# define ReadDataPending(fp) (fp->state.eof == 0)
+# define READ_DATA_PENDING(fp) (fp->state.eof == 0)
#else
/* requires systems own version of the ReadDataPending() */
extern int ReadDataPending();
@@ -1014,9 +1015,9 @@ rb_io_binmode(io)
rb_sys_fail(fptr->path);
# else /* USE_CWGUSI */
if (fptr->f)
- fptr->f->mode.binrb_ary_io = 1;
+ fptr->f->mode.binary_io = 1;
if (fptr->f2)
- fptr->f2->mode.binrb_ary_io = 1;
+ fptr->f2->mode.binary_io = 1;
# endif /* USE_CWGUSI */
#endif
@@ -1025,7 +1026,7 @@ rb_io_binmode(io)
return io;
}
-int
+static int
rb_io_mode_flags(mode)
char *mode;
{
@@ -1042,7 +1043,8 @@ rb_io_mode_flags(mode)
flags |= FMODE_WRITABLE;
break;
default:
- rb_raise(rb_eArgError, "illegal access mode");
+ error:
+ rb_raise(rb_eArgError, "illegal access mode %s", mode);
}
if (mode[1] == 'b') {
@@ -1052,29 +1054,112 @@ rb_io_mode_flags(mode)
if (mode[1] == '+') {
flags |= FMODE_READWRITE;
+ if (mode[2] != 0) goto error;
}
+ else if (mode[1] != 0) goto error;
return flags;
}
+static int
+rb_io_mode_flags2(mode)
+ int mode;
+{
+ int flags;
+
+ switch (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
+ case O_RDONLY:
+ flags = FMODE_READABLE;
+ break;
+ case O_WRONLY:
+ flags = FMODE_WRITABLE;
+ break;
+ case O_RDWR:
+ flags = FMODE_WRITABLE|FMODE_READABLE;
+ break;
+ }
+
+#ifdef O_BINARY
+ if (mode & O_BINARY) {
+ flags |= FMODE_BINMODE;
+ }
+#endif
+
+ return flags;
+}
+
+static char*
+rb_io_flags_mode(flags)
+ int flags;
+{
+ static char mode[4];
+ char *p = mode;
+
+ switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
+ case O_RDONLY:
+ *p++ = 'r';
+ break;
+ case O_WRONLY:
+ *p++ = 'w';
+ break;
+ case O_RDWR:
+ *p++ = 'w';
+ *p++ = '+';
+ break;
+ }
+ *p++ = '\0';
+#ifdef O_BINARY
+ if (flags & O_BINARY) {
+ if (mode[1] == '+') {
+ mode[1] = 'b'; mode[2] = '+'; mode[3] = '\0';
+ }
+ else {
+ mode[1] = 'b'; mode[2] = '\0';
+ }
+ }
+#endif
+ return mode;
+}
+
+static int
+rb_open(fname, flag, mode)
+ char *fname;
+ int flag;
+ mode_t mode;
+{
+ int fd;
+
+ fd = open(fname, flag, mode);
+ if (fd < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ fd = open(fname, flag, mode);
+ }
+ if (fd < 0) {
+ rb_sys_fail(fname);
+ }
+ }
+ return fd;
+}
+
FILE *
rb_fopen(fname, mode)
char *fname;
char *mode;
{
- FILE *f;
+ FILE *file;
- f = fopen(fname, mode);
- if (f == NULL) {
+ file = fopen(fname, mode);
+ if (file == NULL) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
- f = fopen(fname, mode);
+ file = fopen(fname, mode);
}
- if (f == NULL) {
+ if (file == NULL) {
rb_sys_fail(fname);
}
}
- return f;
+ return file;
}
FILE *
@@ -1082,18 +1167,64 @@ rb_fdopen(fd, mode)
int fd;
char *mode;
{
- FILE *f;
+ FILE *file;
- f = fdopen(fd, mode);
- if (f == NULL) {
- if (errno == EMFILE) {
- f = fdopen(fd, mode);
+ file = fdopen(fd, mode);
+ if (file == NULL) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ file = fdopen(fd, mode);
}
- if (f == NULL) {
+ if (file == NULL) {
rb_sys_fail(0);
}
}
- return f;
+ return file;
+}
+
+VALUE
+rb_file_open(fname, mode)
+ char *fname, *mode;
+{
+ OpenFile *fptr;
+ NEWOBJ(port, struct RFile);
+ OBJSETUP(port, rb_cFile, T_FILE);
+ MakeOpenFile(port, fptr);
+
+ fptr->mode = rb_io_mode_flags(mode);
+ fptr->f = rb_fopen(fname, mode);
+ fptr->path = strdup(fname);
+ rb_obj_call_init((VALUE)port);
+
+ return (VALUE)port;
+}
+
+VALUE
+rb_file_sysopen(fname, flags, mode)
+ char *fname;
+ int flags, mode;
+{
+#ifdef USE_CWGUSI
+ if (mode != 0666) {
+ rb_warn("can't specify file mode on this platform");
+ }
+ return rb_file_open(fname, rb_io_flags_mode(flags));
+#else
+ OpenFile *fptr;
+ int fd;
+ char *m;
+ NEWOBJ(port, struct RFile);
+ OBJSETUP(port, rb_cFile, T_FILE);
+ MakeOpenFile(port, fptr);
+
+ fd = rb_open(fname, flags, mode);
+ fptr->mode = rb_io_mode_flags2(flags);
+ fptr->f = rb_fdopen(fd, m);
+ fptr->path = strdup(fname);
+ rb_obj_call_init((VALUE)port);
+
+ return (VALUE)port;
+#endif
}
#if defined (NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__)
@@ -1329,15 +1460,41 @@ rb_io_s_popen(argc, argv, self)
}
static VALUE
-rb_io_open(fname, mode)
- char *fname, *mode;
+rb_file_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
{
- if (fname[0] == '|') {
- return pipe_open(fname+1, mode);
+ VALUE fname, vmode, file, perm;
+ char *path, *mode;
+
+ rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
+ Check_SafeStr(fname);
+ path = RSTRING(fname)->ptr;
+
+ if (FIXNUM_P(vmode)) {
+ int flags = FIX2INT(vmode);
+ int fmode = NIL_P(perm) ? 0666 : FIX2INT(perm);
+
+ file = rb_file_sysopen(path, flags, fmode);
}
else {
- return rb_file_open(fname, mode);
+ if (!NIL_P(vmode)) {
+ mode = STR2CSTR(vmode);
+ }
+ else {
+ mode = "r";
+ }
+ file = rb_file_open(RSTRING(fname)->ptr, mode);
}
+
+ RBASIC(file)->klass = klass;
+ rb_obj_call_init(file);
+ if (rb_iterator_p()) {
+ return rb_ensure(rb_yield, file, rb_io_close, file);
+ }
+
+ return file;
}
static VALUE
@@ -1346,24 +1503,31 @@ rb_f_open(argc, argv)
VALUE *argv;
{
char *mode;
- VALUE pname, pmode;
+ VALUE pname, pmode, perm;
VALUE port;
- rb_scan_args(argc, argv, "11", &pname, &pmode);
+ rb_scan_args(argc, argv, "12", &pname, &pmode, &perm);
Check_SafeStr(pname);
+ if (RSTRING(pname)->ptr[0] != '|') /* open file */
+ return rb_file_s_open(argc, argv, rb_cFile);
+
+ /* open pipe */
if (NIL_P(pmode)) {
mode = "r";
}
+ else if (FIXNUM_P(pmode)) {
+ mode = rb_io_flags_mode(FIX2INT(pmode));
+ }
else {
int len;
mode = STR2CSTR(pmode);
len = strlen(mode);
if (len == 0 || len > 3)
- rb_raise(rb_eArgError, "illegal access mode");
+ rb_raise(rb_eArgError, "illegal access mode %s", mode);
}
- port = rb_io_open(RSTRING(pname)->ptr, mode);
+ port = pipe_open(RSTRING(pname)->ptr+1, mode);
if (rb_iterator_p()) {
return rb_ensure(rb_yield, port, rb_io_close, port);
}
@@ -1372,6 +1536,18 @@ rb_f_open(argc, argv)
}
static VALUE
+rb_io_open(fname, mode)
+ char *fname, *mode;
+{
+ if (fname[0] == '|') {
+ return pipe_open(fname+1, mode);
+ }
+ else {
+ return rb_file_open(fname, mode);
+ }
+}
+
+static VALUE
rb_io_get_io(io)
VALUE io;
{
@@ -1393,7 +1569,7 @@ rb_io_mode_string(fptr)
}
}
-VALUE
+static VALUE
rb_io_reopen(io, nfile)
VALUE io, nfile;
{
@@ -1458,6 +1634,56 @@ rb_io_reopen(io, nfile)
}
static VALUE
+rb_file_reopen(argc, argv, file)
+ int argc;
+ VALUE *argv;
+ VALUE file;
+{
+ VALUE fname, nmode;
+ char *mode;
+ OpenFile *fptr;
+
+ rb_secure(4);
+ if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
+ if (TYPE(fname) == T_FILE) { /* fname must be IO */
+ return rb_io_reopen(file, fname);
+ }
+ }
+
+ Check_SafeStr(fname);
+ if (!NIL_P(nmode)) {
+ mode = STR2CSTR(nmode);
+ }
+ else {
+ mode = "r";
+ }
+
+ GetOpenFile(file, fptr);
+ if (fptr->path) free(fptr->path);
+ fptr->path = strdup(RSTRING(fname)->ptr);
+ fptr->mode = rb_io_mode_flags(mode);
+ if (!fptr->f) {
+ fptr->f = rb_fopen(RSTRING(fname)->ptr, mode);
+ if (fptr->f2) {
+ fclose(fptr->f2);
+ fptr->f2 = NULL;
+ }
+ return file;
+ }
+
+ if (freopen(RSTRING(fname)->ptr, mode, fptr->f) == NULL) {
+ rb_sys_fail(fptr->path);
+ }
+ if (fptr->f2) {
+ if (freopen(RSTRING(fname)->ptr, "w", fptr->f2) == NULL) {
+ rb_sys_fail(fptr->path);
+ }
+ }
+
+ return file;
+}
+
+static VALUE
rb_io_clone(io)
VALUE io;
{
@@ -1870,8 +2096,7 @@ next_argv()
#endif
}
fw = rb_fopen(fn, "w");
-#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__)\
- && !defined(USE_CWGUSI) && !defined(__BEOS__)
+#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__)
fstat(fileno(fw), &st2);
fchmod(fileno(fw), st.st_mode);
if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
@@ -1900,7 +2125,12 @@ rb_f_gets_internal(argc, argv)
retry:
if (!next_argv()) return Qnil;
- line = rb_io_gets_internal(argc, argv, file);
+ if (rb_rs == rb_default_rs) {
+ line = rb_io_gets(file);
+ }
+ else {
+ line = rb_io_gets_internal(argc, argv, file);
+ }
if (NIL_P(line) && next_p != -1) {
rb_io_close(file);
next_p = 1;
@@ -1928,6 +2158,10 @@ rb_gets()
{
VALUE line;
+ if (rb_rs != rb_default_rs) {
+ return rb_f_gets(0, 0);
+ }
+
retry:
if (!next_argv()) return Qnil;
line = rb_io_gets(file);
@@ -2452,8 +2686,8 @@ rb_io_s_pipe()
#endif
rb_sys_fail(0);
- r = prep_stdio(fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO);
- w = prep_stdio(fdopen(pipes[1], "w"), FMODE_WRITABLE, rb_cIO);
+ r = prep_stdio(rb_fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO);
+ w = prep_stdio(rb_fdopen(pipes[1], "w"), FMODE_WRITABLE, rb_cIO);
ary = rb_ary_new2(2);
rb_ary_push(ary, r);
@@ -2550,7 +2784,7 @@ arg_read(argc, argv)
VALUE *argv;
{
VALUE tmp, str;
- size_t len;
+ int len;
if (argc == 1) len = NUM2INT(argv[0]);
str = Qnil;
@@ -2866,4 +3100,30 @@ Init_IO()
#endif
Init_File();
+
+ rb_define_method(rb_cFile, "reopen", rb_file_reopen, -1);
+
+ rb_define_singleton_method(rb_cFile, "new", rb_file_s_open, -1);
+ rb_define_singleton_method(rb_cFile, "open", rb_file_s_open, -1);
+
+ rb_file_const("RDONLY", INT2FIX(O_RDONLY));
+ rb_file_const("WRONLY", INT2FIX(O_WRONLY));
+ rb_file_const("RDWR", INT2FIX(O_RDWR));
+ rb_file_const("APPEND", INT2FIX(O_APPEND));
+ rb_file_const("CREAT", INT2FIX(O_CREAT));
+ rb_file_const("EXCL", INT2FIX(O_EXCL));
+#if defined(O_NDELAY) || defined(O_NONBLOCK)
+# ifdef O_NONBLOCK
+ rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
+# else
+ rb_file_const("NONBLOCK", INT2FIX(O_NDELAY));
+# endif
+#endif
+ rb_file_const("TRUNC", INT2FIX(O_TRUNC));
+#ifdef O_NOCTTY
+ rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
+#endif
+#ifdef O_BINARY
+ rb_file_const("BINARY", INT2FIX(O_BINARY));
+#endif
}