diff options
Diffstat (limited to 'io.c')
-rw-r--r-- | io.c | 507 |
1 files changed, 388 insertions, 119 deletions
@@ -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,10 +54,14 @@ struct timeval { #include <sys/errno.h> #include <unix.mac.h> #include <compat.h> + extern char* strdup(const char*); #endif extern void Init_File _((void)); #ifdef __BEOS__ +# ifdef _X86_ +# define NOFILE (OPEN_MAX) +# endif #include <net/socket.h> #endif @@ -99,7 +103,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(); @@ -110,7 +114,10 @@ extern int ReadDataPending(); # define READ_CHECK(fp) 0 #else # define READ_CHECK(fp) do {\ - if (!READ_DATA_PENDING(fp)) rb_thread_wait_fd(fileno(fp));\ + if (!READ_DATA_PENDING(fp)) {\ + rb_thread_wait_fd(fileno(fp));\ + rb_io_check_closed(fptr);\ + }\ } while(0) #endif @@ -840,8 +847,14 @@ static void rb_io_fptr_close(fptr) OpenFile *fptr; { + int fd; + if (fptr->f == NULL && fptr->f2 == NULL) return; +#ifdef USE_THREAD + rb_thread_fd_close(fileno(fptr->f)); +#endif + if (fptr->finalize) { (*fptr->finalize)(fptr); } @@ -953,7 +966,9 @@ rb_io_syswrite(io, str) f = GetWriteFile(fptr); #ifdef USE_THREAD - rb_thread_fd_writable(fileno(f)); + if (!rb_thread_fd_writable(fileno(f))) { + rb_io_check_closed(fptr); + } #endif n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len); @@ -1014,9 +1029,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 +1040,7 @@ rb_io_binmode(io) return io; } -int +static int rb_io_mode_flags(mode) char *mode; { @@ -1042,7 +1057,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 +1068,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; + unsigned int 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 +1181,65 @@ 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, 0, 0); + + 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); + m = rb_io_flags_mode(flags); + fptr->mode = rb_io_mode_flags2(flags); + fptr->f = rb_fdopen(fd, m); + fptr->path = strdup(fname); + rb_obj_call_init((VALUE)port, 0, 0); + + return (VALUE)port; +#endif } #if defined (NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__) @@ -1205,7 +1351,7 @@ pipe_open(pname, mode) fptr->f2 = f; rb_io_unbuffered(fptr); } - rb_obj_call_init((VALUE)port); + rb_obj_call_init((VALUE)port, 0, 0); return (VALUE)port; } #else @@ -1293,7 +1439,7 @@ pipe_open(pname, mode) fptr->finalize = pipe_finalize; pipe_add_fptr(fptr); #endif - rb_obj_call_init((VALUE)port); + rb_obj_call_init((VALUE)port, 0, 0); return (VALUE)port; } } @@ -1329,15 +1475,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, 0, 0); + if (rb_iterator_p()) { + return rb_ensure(rb_yield, file, rb_io_close, file); + } + + return file; } static VALUE @@ -1346,24 +1518,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 +1551,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 +1584,7 @@ rb_io_mode_string(fptr) } } -VALUE +static VALUE rb_io_reopen(io, nfile) VALUE io, nfile; { @@ -1412,6 +1603,9 @@ rb_io_reopen(io, nfile) else if (orig->mode & FMODE_WRITABLE) { fflush(orig->f); } +#ifdef USE_THREAD + rb_thread_fd_close(fileno(fptr->f)); +#endif /* copy OpenFile structure */ fptr->mode = orig->mode; @@ -1458,6 +1652,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; { @@ -1772,7 +2016,7 @@ prep_stdio(f, mode, klass) MakeOpenFile(io, fp); fp->f = f; fp->mode = mode; - rb_obj_call_init((VALUE)io); + rb_obj_call_init((VALUE)io, 0, 0); return (VALUE)io; } @@ -1870,8 +2114,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 +2143,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 +2176,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); @@ -1960,76 +2212,13 @@ rb_f_readline(argc, argv) } static VALUE -rb_f_tell() -{ - return rb_io_tell(file); -} - -static VALUE -rb_f_seek(self, offset, ptrname) - VALUE self, offset, ptrname; -{ - if (!next_argv()) { - rb_raise(rb_eArgError, "no stream to seek"); - } - - return rb_io_seek(file, offset, ptrname); -} - -static VALUE -rb_f_set_pos(self, offset) - VALUE self, offset; -{ - if (!next_argv()) { - rb_raise(rb_eArgError, "no stream to pos"); - } - - return rb_io_set_pos(file, offset); -} - -static VALUE -rb_f_rewind() -{ - return rb_io_rewind(file); -} - -static VALUE -rb_f_eof() -{ - if (init_p == 0 && !next_argv()) - return Qtrue; - if (rb_io_eof(file)) { - next_p = 1; - return Qtrue; - } - return Qfalse; -} - -static VALUE rb_f_getc() { + rb_warn("getc is obsolete; use STDIN.getc instead"); return rb_io_getc(rb_stdin); } static VALUE -rb_f_ungetc(self, c) - VALUE self, c; -{ - return rb_io_ungetc(rb_stdin, c); -} - -static VALUE -rb_f_readchar() -{ - VALUE c = rb_f_getc(); - - if (NIL_P(c)) { - rb_eof_error(); - } - return c; -} - -static VALUE rb_f_readlines(argc, argv) int argc; VALUE *argv; @@ -2452,8 +2641,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); @@ -2466,6 +2655,13 @@ rb_io_s_pipe() #endif } +static VALUE +rb_f_pipe() +{ + rb_warn("pipe is obsolete; use IO::pipe instead"); + return rb_io_s_pipe(); +} + struct foreach_arg { int argc; VALUE sep; @@ -2533,6 +2729,40 @@ rb_io_s_readlines(argc, argv, io) } static VALUE +arg_tell() +{ + return rb_io_tell(file); +} + +static VALUE +arg_seek(self, offset, ptrname) + VALUE self, offset, ptrname; +{ + if (!next_argv()) { + rb_raise(rb_eArgError, "no stream to seek"); + } + + return rb_io_seek(file, offset, ptrname); +} + +static VALUE +arg_set_pos(self, offset) + VALUE self, offset; +{ + if (!next_argv()) { + rb_raise(rb_eArgError, "no stream to pos"); + } + + return rb_io_set_pos(file, offset); +} + +static VALUE +arg_rewind() +{ + return rb_io_rewind(file); +} + +static VALUE arg_fileno() { return rb_io_fileno(file); @@ -2550,7 +2780,7 @@ arg_read(argc, argv) VALUE *argv; { VALUE tmp, str; - size_t len; + int len; if (argc == 1) len = NUM2INT(argv[0]); str = Qnil; @@ -2607,6 +2837,25 @@ arg_readchar() } static VALUE +arg_eof() +{ + if (init_p == 0 && !next_argv()) + return Qtrue; + if (rb_io_eof(file)) { + next_p = 1; + return Qtrue; + } + return Qfalse; +} + +static VALUE +rb_f_eof() +{ + rb_warn("eof? is obsolete; use ARGF.eof? instead"); + return arg_eof(); +} + +static VALUE arg_each_line(argc, argv) int argc; VALUE *argv; @@ -2704,20 +2953,15 @@ Init_IO() rb_define_global_function("puts", rb_f_puts, -1); rb_define_global_function("gets", rb_f_gets, -1); rb_define_global_function("readline", rb_f_readline, -1); - rb_define_global_function("tell", rb_f_tell, 0); - rb_define_global_function("seek", rb_f_seek, 2); - rb_define_global_function("rewind", rb_f_rewind, 0); rb_define_global_function("eof", rb_f_eof, 0); rb_define_global_function("eof?", rb_f_eof, 0); rb_define_global_function("getc", rb_f_getc, 0); - rb_define_global_function("readchar", rb_f_readchar, 0); rb_define_global_function("select", rb_f_select, -1); - rb_define_global_function("ungetc", rb_f_ungetc, 1); rb_define_global_function("readlines", rb_f_readlines, -1); rb_define_global_function("`", rb_f_backquote, 1); - rb_define_global_function("pipe", rb_io_s_pipe, 0); + rb_define_global_function("pipe", rb_f_pipe, 0); rb_define_global_function("p", rb_f_p, -1); rb_define_method(rb_mKernel, "display", rb_obj_display, -1); @@ -2838,14 +3082,13 @@ Init_IO() rb_define_singleton_method(argf, "readline", rb_f_readline, -1); rb_define_singleton_method(argf, "getc", arg_getc, 0); rb_define_singleton_method(argf, "readchar", arg_readchar, 0); - rb_define_singleton_method(argf, "tell", rb_f_tell, 0); - rb_define_singleton_method(argf, "seek", rb_f_seek, 2); - rb_define_singleton_method(argf, "rewind", rb_f_rewind, 0); - rb_define_singleton_method(argf, "pos", rb_f_tell, 0); - rb_define_singleton_method(argf, "pos=", rb_f_set_pos, 1); - rb_define_singleton_method(argf, "eof", rb_f_eof, 0); - rb_define_singleton_method(argf, "eof?", rb_f_eof, 0); - rb_define_singleton_method(argf, "ungetc", rb_f_ungetc, 1); + rb_define_singleton_method(argf, "tell", arg_tell, 0); + rb_define_singleton_method(argf, "seek", arg_seek, 2); + rb_define_singleton_method(argf, "rewind", arg_rewind, 0); + rb_define_singleton_method(argf, "pos", arg_tell, 0); + rb_define_singleton_method(argf, "pos=", arg_set_pos, 1); + rb_define_singleton_method(argf, "eof", arg_eof, 0); + rb_define_singleton_method(argf, "eof?", arg_eof, 0); rb_define_singleton_method(argf, "to_s", arg_filename, 0); rb_define_singleton_method(argf, "filename", arg_filename, 0); @@ -2866,4 +3109,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 } |