diff --git a/src/modules/files/file.c b/src/modules/files/file.c index b4d51c9ed2c50e349bfbed0e2b53ba539346b7af..29087963965105024bbaacf6876aec476e6624b3 100644 --- a/src/modules/files/file.c +++ b/src/modules/files/file.c @@ -1,12 +1,11 @@ -/* \ +/*\ ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License) ||| See the files COPYING and DISCLAIMER for more information. -\ */ -#define READ_BUFFER 8192 +\*/ #include "global.h" -RCSID("$Id: file.c,v 1.83 1998/03/26 14:31:01 grubba Exp $"); +RCSID("$Id: file.c,v 1.84 1998/04/06 04:34:05 hubbe Exp $"); #include "fdlib.h" #include "interpret.h" #include "svalue.h" @@ -77,142 +76,184 @@ RCSID("$Id: file.c,v 1.83 1998/03/26 14:31:01 grubba Exp $"); #include "dmalloc.h" - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -struct file_struct -{ - short fd; - short my_errno; -}; - -#define FD (((struct file_struct *)(fp->current_storage))->fd) -#define ERRNO (((struct file_struct *)(fp->current_storage))->my_errno) #undef THIS -#define THIS (files + FD) +#define THIS ((struct my_file *)(fp->current_storage)) +#define FD (THIS->fd) +#define ERRNO (THIS->my_errno) + +#define READ_BUFFER 8192 -static struct my_file files[MAX_OPEN_FILEDESCRIPTORS]; static struct program *file_program; +static struct program *file_ref_program; static void file_read_callback(int fd, void *data); static void file_write_callback(int fd, void *data); -static void init_fd(int fd, int open_mode) +static struct my_file *get_file_storage(struct object *o) { - files[fd].refs=1; - files[fd].open_mode=open_mode; - files[fd].id.type=T_INT; - files[fd].id.u.integer=0; - files[fd].read_callback.type=T_INT; - files[fd].read_callback.u.integer=0; - files[fd].write_callback.type=T_INT; - files[fd].write_callback.u.integer=0; -#ifdef WITH_OOB - files[fd].read_oob_callback.type=T_INT; - files[fd].read_oob_callback.u.integer=0; - files[fd].write_oob_callback.type=T_INT; - files[fd].write_oob_callback.u.integer=0; -#endif /* WITH_OOB */ - files[fd].close_callback.type=T_INT; - files[fd].close_callback.u.integer=0; + struct my_file *f; + struct object **ob; + if(o->prog == file_program) + return ((struct my_file *)(o->storage)); + + if((f=(struct my_file *)get_storage(o,file_program))) + return f; + + if((ob=(struct object **)get_storage(o,file_ref_program))) + if(*ob && (f=(struct my_file *)get_storage(*ob, file_program))) + return f; + + return 0; } -static int close_fd(int fd) -{ #ifdef DEBUG - if(fd < 0 || fd >= MAX_OPEN_FILEDESCRIPTORS) - fatal("Bad argument to close_fd()\n"); - - if(files[fd].refs<1) - fatal("Wrong ref count in file struct\n"); +#ifdef WITH_OOB +#define OOBOP(X) (X) +#else +#define OOBOP(X) #endif +#define CHECK_FILEP(o) \ +do { if(o->prog && !get_storage(o,file_program)) fatal("%p is not a file object.\n",o); } while (0) +#define DEBUG_CHECK_INTERNAL_REFERENCE(X) do { \ + if( ((X)->fd!=-1 && ( \ + query_read_callback((X)->fd)==file_read_callback || \ + query_write_callback((X)->fd)==file_write_callback \ +OOBOP( || query_read_oob_callback((X)->fd)==file_read_oob_callback || \ + query_write_oob_callback((X)->fd)==file_write_oob_callback ))) != \ + !!( (X)->flags & FILE_HAS_INTERNAL_REF )) \ + fatal("Internal reference is wrong. %d\n",(X)->flags & FILE_HAS_INTERNAL_REF); \ + } while (0) +#else +#define CHECK_FILEP(o) +#define DEBUG_CHECK_INTERNAL_REFERENCE(X) +#endif +#define SET_INTERNAL_REFERENCE(f) \ + do { CHECK_FILEP(f->myself); if(!(f->flags & FILE_HAS_INTERNAL_REF)) { f->myself->refs++; f->flags|=FILE_HAS_INTERNAL_REF; } }while (0) - files[fd].refs--; - if(!files[fd].refs) +#define REMOVE_INTERNAL_REFERENCE(f) \ + do { CHECK_FILEP(f->myself); if(f->flags & FILE_HAS_INTERNAL_REF) { f->flags&=~FILE_HAS_INTERNAL_REF; free_object(f->myself); } }while (0) + +static void check_internal_reference(struct my_file *f) +{ + if(f->fd!=-1) { - set_read_callback(fd,0,0); - set_write_callback(fd,0,0); + if(query_read_callback(f->fd) == file_read_callback || + query_write_callback(f->fd) == file_write_callback #ifdef WITH_OOB - set_read_oob_callback(fd,0,0); - set_write_oob_callback(fd,0,0); -#endif /* WITH_OOB */ + || query_read_oob_callback(f->fd) == file_read_oob_callback || + query_write_oob_callback(f->fd) == file_write_oob_callback +#endif + ) + { + SET_INTERNAL_REFERENCE(f); + return; + } + } + + REMOVE_INTERNAL_REFERENCE(f); +} - free_svalue(& files[fd].id); - free_svalue(& files[fd].read_callback); - free_svalue(& files[fd].write_callback); +static void init_fd(int fd, int open_mode) +{ + FD=fd; + ERRNO=0; + REMOVE_INTERNAL_REFERENCE(THIS); + THIS->flags=0; + THIS->open_mode=open_mode; + THIS->read_callback.type=T_INT; + THIS->read_callback.u.integer=0; + THIS->write_callback.type=T_INT; + THIS->write_callback.u.integer=0; #ifdef WITH_OOB - free_svalue(& files[fd].read_oob_callback); - free_svalue(& files[fd].write_oob_callback); + THIS->read_oob_callback.type=T_INT; + THIS->read_oob_callback.u.integer=0; + THIS->write_oob_callback.type=T_INT; + THIS->write_oob_callback.u.integer=0; #endif /* WITH_OOB */ - free_svalue(& files[fd].close_callback); - files[fd].id.type=T_INT; - files[fd].read_callback.type=T_INT; - files[fd].write_callback.type=T_INT; +#ifdef HAVE_FD_FLOCK + THIS->key=0; +#endif +} + + +void reset_variables(void) +{ + free_svalue(& THIS->read_callback); + THIS->read_callback.type=T_INT; + free_svalue(& THIS->write_callback); + THIS->write_callback.type=T_INT; #ifdef WITH_OOB - files[fd].read_oob_callback.type=T_INT; - files[fd].write_oob_callback.type=T_INT; + free_svalue(& THIS->read_oob_callback); + THIS->read_oob_callback.type=T_INT; + free_svalue(& THIS->write_oob_callback); + THIS->write_oob_callback.type=T_INT; #endif /* WITH_OOB */ - files[fd].close_callback.type=T_INT; - files[fd].open_mode = 0; +} +static void free_fd_stuff(void) +{ #ifdef HAVE_FD_FLOCK - if(files[fd].key) - { - destruct(files[fd].key); - files[fd].key=0; - } + if(THIS->key) + { + destruct(THIS->key); + THIS->key=0; + } #endif + check_internal_reference(THIS); +} + +static void just_close_fd() +{ + int fd=FD; + if(fd<0) return; + + set_read_callback(FD,0,0); + set_write_callback(FD,0,0); +#ifdef WITH_OOB + set_read_oob_callback(FD,0,0); + set_write_oob_callback(FD,0,0); +#endif /* WITH_OOB */ + check_internal_reference(THIS); - while(1) + while(1) + { + int i; + THREADS_ALLOW(); + i=fd_close(fd); + THREADS_DISALLOW(); + + if(i < 0) { - int i; - THREADS_ALLOW(); - i=fd_close(fd); - THREADS_DISALLOW(); - - if(i < 0) + switch(errno) { - switch(errno) - { default: - /* What happened? */ - /* files[fd].errno=errno; */ - - /* Try waiting it out in blocking mode */ - set_nonblocking(fd,0); - THREADS_ALLOW(); - i=fd_close(fd); - THREADS_DISALLOW(); - if(i>= 0 || errno==EBADF) break; /* It was actually closed, good! */ - - /* Failed, give up, crash, burn, die */ + ERRNO=errno; error("Failed to close file.\n"); - + case EBADF: error("Internal error: Closing a non-active file descriptor %d.\n",fd); case EINTR: continue; - } } - break; } + break; } - return 0; + FD=-1; +} + +static void close_fd(void) +{ + free_fd_stuff(); + reset_variables(); + just_close_fd(); } void my_set_close_on_exec(int fd, int to) { +#if 1 + set_close_on_exec(fd, 0); +#else if(to) { files[fd].open_mode |= FILE_SET_CLOSE_ON_EXEC; @@ -222,10 +263,12 @@ void my_set_close_on_exec(int fd, int to) else set_close_on_exec(fd, 0); } +#endif } void do_set_close_on_exec(void) { +#if 0 int e; for(e=0;e<MAX_OPEN_FILEDESCRIPTORS;e++) { @@ -235,6 +278,7 @@ void do_set_close_on_exec(void) files[e].open_mode &=~ FILE_SET_CLOSE_ON_EXEC; } } +#endif } /* Parse "rw" to internal flags */ @@ -305,7 +349,7 @@ static void free_dynamic_buffer(dynamic_buffer *b) { free(b->s.str); } static struct pike_string *do_read(int fd, INT32 r, int all, - short *err) + int *err) { ONERROR ebuf; INT32 bytes_read,i; @@ -353,6 +397,12 @@ static struct pike_string *do_read(int fd, UNSET_ONERROR(ebuf); + if(!IS_ZERO(& THIS->read_callback)) + { + set_read_callback(FD, file_read_callback, THIS); + SET_INTERNAL_REFERENCE(THIS); + } + if(bytes_read == str->len) { return end_shared_string(str); @@ -419,6 +469,14 @@ static struct pike_string *do_read(int fd, }while(r); UNSET_ONERROR(ebuf); + + if(!IS_ZERO(& THIS->read_callback)) + { + set_read_callback(FD, file_read_callback, THIS); + SET_INTERNAL_REFERENCE(THIS); + } + + return low_free_buf(&b); } } @@ -427,7 +485,7 @@ static struct pike_string *do_read(int fd, static struct pike_string *do_read_oob(int fd, INT32 r, int all, - short *err) + int *err) { ONERROR ebuf; INT32 bytes_read,i; @@ -475,6 +533,12 @@ static struct pike_string *do_read_oob(int fd, UNSET_ONERROR(ebuf); + if(!IS_ZERO(& THIS->read_oob_callback)) + { + set_read_callback(FD, file_read_oob_callback, THIS); + SET_INTERNAL_REFERENCE(THIS); + } + if(bytes_read == str->len) { return end_shared_string(str); @@ -541,6 +605,11 @@ static struct pike_string *do_read_oob(int fd, }while(r); UNSET_ONERROR(ebuf); + if(!IS_ZERO(& THIS->read_oob_callback)) + { + set_read_callback(FD, file_read_oob_callback, THIS); + SET_INTERNAL_REFERENCE(THIS); + } return low_free_buf(&b); } } @@ -620,25 +689,48 @@ static void file_read_oob(INT32 args) } #endif /* WITH_OOB */ -static void file_write_callback(int fd, void *data) -{ - set_write_callback(fd, 0, 0); - - assign_svalue_no_free(sp++, & files[fd].id); - apply_svalue(& files[fd].write_callback, 1); - pop_stack(); -} - +#undef CBFUNCS +#define CBFUNCS(X) \ +static void PIKE_CONCAT(file_,X) (int fd, void *data) \ +{ \ + struct my_file *f=(struct my_file *)data; \ + PIKE_CONCAT(set_,X)(fd, 0, 0); \ + check_internal_reference(f); \ + check_destructed(& f->X ); \ + if(!IS_ZERO(& f->X )) { \ + apply_svalue(& f->X, 0); \ + pop_stack(); \ + } \ +} \ + \ +static void PIKE_CONCAT(file_set_,X) (INT32 args) \ +{ \ + if(!args) \ + error("Too few arguments to %s\n",#X); \ + assign_svalue(& THIS->X, sp-args); \ + if(IS_ZERO(sp-args)) \ + { \ + PIKE_CONCAT(set_,X)(FD, 0, 0); \ + check_internal_reference(THIS); \ + }else{ \ + PIKE_CONCAT(set_,X)(FD, PIKE_CONCAT(file_,X), THIS); \ + SET_INTERNAL_REFERENCE(THIS); \ + } \ +} \ + \ +static void PIKE_CONCAT(file_query_,X) (INT32 args) \ +{ \ + pop_n_elems(args); \ + push_svalue(& THIS->X); \ +} + +CBFUNCS(read_callback) +CBFUNCS(write_callback) #ifdef WITH_OOB -static void file_write_oob_callback(int fd, void *data) -{ - set_write_oob_callback(fd, 0, 0); +CBFUNCS(read_oob_callback) +CBFUNCS(write_oob_callback) +#endif - assign_svalue_no_free(sp++, & files[fd].id); - apply_svalue(& files[fd].write_oob_callback, 1); - pop_stack(); -} -#endif /* WITH_OOB */ static void file_write(INT32 args) { @@ -696,7 +788,10 @@ static void file_write(INT32 args) } if(!IS_ZERO(& THIS->write_callback)) - set_write_callback(FD, file_write_callback, 0); + { + set_write_callback(FD, file_write_callback, THIS); + SET_INTERNAL_REFERENCE(THIS); + } ERRNO=0; pop_n_elems(args); @@ -760,7 +855,11 @@ static void file_write_oob(INT32 args) } if(!IS_ZERO(& THIS->write_oob_callback)) - set_write_oob_callback(FD, file_write_oob_callback, 0); + { + set_write_oob_callback(FD, file_write_oob_callback, THIS); + SET_INTERNAL_REFERENCE(THIS); + } + ERRNO=0; pop_n_elems(args); @@ -768,16 +867,12 @@ static void file_write_oob(INT32 args) } #endif /* WITH_OOB */ -static int do_close(int fd, int flags) +static int do_close(int flags) { - if(fd == -1) return 1; /* already closed */ - - /* files[fd].errno=0; */ - - if(!(files[fd].open_mode & (FILE_READ | FILE_WRITE))) - return 1; + if(FD == -1) return 1; /* already closed */ + ERRNO=0; - flags &= files[fd].open_mode; + flags &= THIS->open_mode; switch(flags & (FILE_READ | FILE_WRITE)) { @@ -785,37 +880,39 @@ static int do_close(int fd, int flags) return 0; case FILE_READ: - if(files[fd].open_mode & FILE_WRITE) + if(THIS->open_mode & FILE_WRITE) { - set_read_callback(fd,0,0); + set_read_callback(FD,0,0); #ifdef WITH_OOB - set_read_oob_callback(fd,0,0); + set_read_oob_callback(FD,0,0); #endif /* WITH_OOB */ - fd_shutdown(fd, 0); - files[fd].open_mode &=~ FILE_READ; + fd_shutdown(FD, 0); + THIS->open_mode &=~ FILE_READ; + check_internal_reference(THIS); return 0; }else{ - close_fd(fd); + close_fd(); return 1; } case FILE_WRITE: - if(files[fd].open_mode & FILE_READ) + if(THIS->open_mode & FILE_READ) { - set_write_callback(fd,0,0); + set_write_callback(FD,0,0); #ifdef WITH_OOB - set_write_oob_callback(fd,0,0); + set_write_oob_callback(FD,0,0); #endif /* WITH_OOB */ - fd_shutdown(fd, 1); - files[fd].open_mode &=~ FILE_WRITE; + fd_shutdown(FD, 1); + THIS->open_mode &=~ FILE_WRITE; + check_internal_reference(THIS); return 0; }else{ - close_fd(fd); + close_fd(); return 1; } case FILE_READ | FILE_WRITE: - close_fd(fd); + close_fd(); return 1; default: @@ -836,18 +933,17 @@ static void file_close(INT32 args) flags=FILE_READ | FILE_WRITE; } - if((files[FD].open_mode & ~flags & (FILE_READ|FILE_WRITE)) && flags) + if((THIS->open_mode & ~flags & (FILE_READ|FILE_WRITE)) && flags) { - if(!(files[FD].open_mode & fd_CAN_SHUTDOWN)) + if(!(THIS->open_mode & fd_CAN_SHUTDOWN)) { error("Cannot close one direction on this file.\n"); } } - if(do_close(FD,flags)) - FD=-1; + flags=do_close(flags); pop_n_elems(args); - push_int(1); + push_int(flags); } static void file_open(INT32 args) @@ -855,8 +951,7 @@ static void file_open(INT32 args) int flags,fd; int access; struct pike_string *str; - do_close(FD, FILE_READ | FILE_WRITE); - FD=-1; + close_fd(); if(args < 2) error("Too few arguments to file->open()\n"); @@ -904,8 +999,6 @@ static void file_open(INT32 args) else { init_fd(fd,flags | fd_query_properties(fd, FILE_CAPABILITIES)); - FD=fd; - ERRNO = 0; set_close_on_exec(fd,1); } @@ -1007,205 +1100,11 @@ static void file_errno(INT32 args) push_int(ERRNO); } -/* Trick compiler to keep 'buffer' in memory for - * as short a time as possible. - * shouldn't be any need to allow threading here, this - * call should never block.. - */ -static struct pike_string *simple_do_read(INT32 *amount,int fd) -{ - char buffer[READ_BUFFER]; - *amount = fd_read(fd, buffer, READ_BUFFER); - if(*amount>0) return make_shared_binary_string(buffer,*amount); - return 0; -} - -#ifdef WITH_OOB -static struct pike_string *simple_do_read_oob(INT32 *amount,int fd) -{ - char buffer[READ_BUFFER]; - *amount = fd_recv(fd, buffer, READ_BUFFER, MSG_OOB); - /* Note: OOB packets may have zero size */ - if(*amount>=0) return make_shared_binary_string(buffer,*amount); - return 0; -} -#endif /* WITH_OOB */ - -static void file_read_callback(int fd, void *data) -{ - struct pike_string *s; - INT32 i; - -#ifdef DEBUG - if(fd == -1 || fd >= MAX_OPEN_FILEDESCRIPTORS) - fatal("Error in file::read_callback()\n"); -#endif - - /* files[fd].errno=0; */ - - s=simple_do_read(&i, fd); - - if(i>0) - { - assign_svalue_no_free(sp++, &files[fd].id); - push_string(s); - apply_svalue(& files[fd].read_callback, 2); - pop_stack(); - return; - } - - if(i < 0) - { - /* files[fd].errno=errno; */ - switch(errno) - { - case EINTR: - case EWOULDBLOCK: - return; - } - } - - set_read_callback(fd, 0, 0); - - /* We _used_ to close the file here, not possible anymore though... */ - /* Hmm, I wonder why... :P */ - assign_svalue_no_free(sp++, &files[fd].id); - apply_svalue(& files[fd].close_callback, 1); -} - -#ifdef WITH_OOB -static void file_read_oob_callback(int fd, void *data) -{ - struct pike_string *s; - INT32 i; - -#ifdef DEBUG - if(fd == -1 || fd >= MAX_OPEN_FILEDESCRIPTORS) - fatal("Error in file::read_oob_callback()\n"); -#endif - - /* files[fd].errno=0; */ - - s=simple_do_read_oob(&i, fd); - - /* Note: OOB ackets may have zero size */ - if(i>=0) - { - assign_svalue_no_free(sp++, &files[fd].id); - push_string(s); - apply_svalue(& files[fd].read_oob_callback, 2); - pop_stack(); - return; - } - - if(i < 0) - { - /* files[fd].errno=errno; */ - switch(errno) - { - case EINTR: - case EWOULDBLOCK: - return; - } - } -} -#endif /* WITH_OOB */ - -static void file_set_read_callback(INT32 args) -{ - if(FD < 0) - error("File is not open.\n"); - - if(args < 1) - error("Too few arguments to file->set_read_callback().\n"); - - assign_svalue(& THIS->read_callback, sp-args); - - if(IS_ZERO(& THIS->read_callback)) - { - set_read_callback(FD, 0, 0); - }else{ - set_read_callback(FD, file_read_callback, 0); - } - pop_n_elems(args); -} - -static void file_set_write_callback(INT32 args) -{ - if(FD < 0) - error("File is not open.\n"); - - if(args < 1) - error("Too few arguments to file->set_write_callback().\n"); - - assign_svalue(& THIS->write_callback, sp-args); - - if(IS_ZERO(& THIS->write_callback)) - { - set_write_callback(FD, 0, 0); - }else{ - set_write_callback(FD, file_write_callback, 0); - } - pop_n_elems(args); -} - -#ifdef WITH_OOB -static void file_set_read_oob_callback(INT32 args) -{ - if(FD < 0) - error("File is not open.\n"); - - if(args < 1) - error("Too few arguments to file->set_read_oob_callback().\n"); - - assign_svalue(& THIS->read_oob_callback, sp-args); - - if(IS_ZERO(& THIS->read_oob_callback)) - { - set_read_oob_callback(FD, 0, 0); - }else{ - set_read_oob_callback(FD, file_read_oob_callback, 0); - } - pop_n_elems(args); -} - -static void file_set_write_oob_callback(INT32 args) -{ - if(FD < 0) - error("File is not open.\n"); - - if(args < 1) - error("Too few arguments to file->set_write_oob_callback().\n"); - - assign_svalue(& THIS->write_oob_callback, sp-args); - - if(IS_ZERO(& THIS->write_oob_callback)) - { - set_write_oob_callback(FD, 0, 0); - }else{ - set_write_oob_callback(FD, file_write_oob_callback, 0); - } - pop_n_elems(args); -} -#endif /* WITH_OOB */ - -static void file_set_close_callback(INT32 args) -{ - if(FD < 0) - error("File is not open.\n"); - - if(args < 1) - error("Too few arguments to file->set_close_callback().\n"); - - assign_svalue(& THIS->close_callback, sp-args); - pop_n_elems(args); -} - static void file_set_nonblocking(INT32 args) { if(FD < 0) error("File not open.\n"); - if(!(files[FD].open_mode & fd_CAN_NONBLOCK)) + if(!(THIS->open_mode & fd_CAN_NONBLOCK)) error("That file does not support nonblocking operation.\n"); if(set_nonblocking(FD,1)) @@ -1214,54 +1113,14 @@ static void file_set_nonblocking(INT32 args) error("Stdio.File->set_nonbloblocking() failed.\n"); } - switch(args) - { -#ifdef WITH_OOB - default: pop_n_elems(args-5); - case 5: file_set_write_oob_callback(1); - case 4: file_set_read_oob_callback(1); -#else /* !WITH_OOB */ - default: pop_n_elems(args-3); -#endif /* WITH_OOB */ - case 3: file_set_close_callback(1); - case 2: file_set_write_callback(1); - case 1: file_set_read_callback(1); - case 0: break; - } THIS->open_mode |= FILE_NONBLOCKING; } static void file_set_blocking(INT32 args) { - free_svalue(& THIS->read_callback); - THIS->read_callback.type=T_INT; - THIS->read_callback.u.integer=0; - free_svalue(& THIS->write_callback); - THIS->write_callback.type=T_INT; - THIS->write_callback.u.integer=0; - -#ifdef WITH_OOB - free_svalue(& THIS->read_oob_callback); - THIS->read_oob_callback.type=T_INT; - THIS->read_oob_callback.u.integer=0; - free_svalue(& THIS->write_oob_callback); - THIS->write_oob_callback.type=T_INT; - THIS->write_oob_callback.u.integer=0; -#endif /* WITH_OOB */ - - free_svalue(& THIS->close_callback); - THIS->close_callback.type=T_INT; - THIS->close_callback.u.integer=0; - if(FD >= 0) { - set_read_callback(FD, 0, 0); - set_write_callback(FD, 0, 0); -#ifdef WITH_OOB - set_read_oob_callback(FD, 0, 0); - set_write_oob_callback(FD, 0, 0); -#endif /* WITH_OOB */ set_nonblocking(FD,0); THIS->open_mode &=~ FILE_NONBLOCKING; } @@ -1284,27 +1143,6 @@ static void file_set_close_on_exec(INT32 args) pop_n_elems(args-1); } -static void file_set_id(INT32 args) -{ - if(args < 1) - error("Too few arguments to file->set_id()\n"); - - if(FD < 0) - error("File not open.\n"); - - assign_svalue(& THIS->id, sp-args); - pop_n_elems(args-1); -} - -static void file_query_id(INT32 args) -{ - if(FD < 0) - error("File not open.\n"); - - pop_n_elems(args); - assign_svalue_no_free(sp++,& THIS->id); -} - static void file_query_fd(INT32 args) { if(FD < 0) @@ -1314,61 +1152,11 @@ static void file_query_fd(INT32 args) push_int(FD); } -static void file_query_read_callback(INT32 args) -{ - if(FD < 0) - error("File not open.\n"); - - pop_n_elems(args); - assign_svalue_no_free(sp++,& THIS->read_callback); -} - -static void file_query_write_callback(INT32 args) -{ - if(FD < 0) - error("File not open.\n"); - - pop_n_elems(args); - assign_svalue_no_free(sp++,& THIS->write_callback); -} - -#ifdef WITH_OOB -static void file_query_read_oob_callback(INT32 args) -{ - if(FD < 0) - error("File not open.\n"); - - pop_n_elems(args); - assign_svalue_no_free(sp++,& THIS->read_oob_callback); -} - -static void file_query_write_oob_callback(INT32 args) -{ - if(FD < 0) - error("File not open.\n"); - - pop_n_elems(args); - assign_svalue_no_free(sp++,& THIS->write_oob_callback); -} -#endif /* WITH_OOB */ - -static void file_query_close_callback(INT32 args) -{ - if(FD < 0) - error("File not open.\n"); - - pop_n_elems(args); - assign_svalue_no_free(sp++,& THIS->close_callback); -} - struct object *file_make_object_from_fd(int fd, int mode, int guess) { - struct object *o; - - init_fd(fd, mode | fd_query_properties(fd, guess)); - o=clone_object(file_program,0); - ((struct file_struct *)(o->storage))->fd=fd; - ((struct file_struct *)(o->storage))->my_errno=0; + struct object *o=clone_object(file_program,0); + ((struct my_file *)(o->storage))->fd=fd; + ((struct my_file *)(o->storage))->open_mode=mode | fd_query_properties(fd, guess); return o; } @@ -1401,7 +1189,7 @@ static void file_set_buffer(INT32 args) #if SOCKET_BUFFER_MAX if(bufsize>SOCKET_BUFFER_MAX) bufsize=SOCKET_BUFFER_MAX; #endif - flags &= files[FD].open_mode; + flags &= THIS->open_mode; if(flags & FILE_READ) { int tmp=bufsize; @@ -1599,8 +1387,7 @@ static void file_pipe(INT32 args) check_all_args("file->pipe",args, BIT_INT | BIT_VOID, 0); if(args) type = sp[-args].u.integer; - do_close(FD,FILE_READ | FILE_WRITE); - FD=-1; + close_fd(); pop_n_elems(args); ERRNO=0; @@ -1669,78 +1456,85 @@ static void file_pipe(INT32 args) static void init_file_struct(struct object *o) { FD=-1; - ERRNO=-1; + ERRNO=0; + THIS->open_mode=0; + THIS->flags=0; + THIS->key=0; + THIS->myself=o; + /* map_variable will take care of the rest */ } static void exit_file_struct(struct object *o) { - do_close(FD,FILE_READ | FILE_WRITE); - ERRNO=-1; -} + if(!(THIS->flags & FILE_NO_CLOSE_ON_DESTRUCT)) + just_close_fd(); + free_fd_stuff(); -static void gc_mark_file_struct(struct object *o) -{ - if(FD>-1) - { - gc_mark_svalues(& THIS->read_callback,1); - gc_mark_svalues(& THIS->write_callback,1); -#ifdef WITH_OOB - gc_mark_svalues(& THIS->read_oob_callback,1); - gc_mark_svalues(& THIS->write_oob_callback,1); -#endif /* WITH_OOB */ - gc_mark_svalues(& THIS->close_callback,1); - gc_mark_svalues(& THIS->id,1); - } + REMOVE_INTERNAL_REFERENCE(THIS); + /* map_variable will free callbacks */ } -static void file_dup(INT32 args) +#ifdef DEBUG +static void gc_mark_file_struct(struct object *o) { - struct object *o; - - if(FD < 0) - error("File not open.\n"); - - pop_n_elems(args); - - o=clone_object(file_program,0); - ((struct file_struct *)o->storage)->fd=FD; - ((struct file_struct *)o->storage)->my_errno=0; - ERRNO=0; - files[FD].refs++; - push_object(o); + DEBUG_CHECK_INTERNAL_REFERENCE(THIS); } +#endif -static void file_assign(INT32 args) +static void low_dup(struct object *toob, + struct my_file *to, + struct my_file *from) { - struct object *o; - - if(args < 1) - error("Too few arguments to file->assign()\n"); - - if(sp[-args].type != T_OBJECT) - error("Bad argument 1 to file->assign()\n"); - - o=sp[-args].u.object; + my_set_close_on_exec(to->fd, to->fd > 2); + REMOVE_INTERNAL_REFERENCE(to); + to->open_mode=from->open_mode; + to->flags=from->flags & ~FILE_HAS_INTERNAL_REF; - /* Actually, we allow any object which first inherit is - * /precompiled/file - */ - if(!o->prog || o->prog->inherits[0].prog != file_program) - error("Argument 1 to file->assign() must be a clone of Stdio.File\n"); - do_close(FD, FILE_READ | FILE_WRITE); + assign_svalue(& to->read_callback, & from->read_callback); + assign_svalue(& to->write_callback, & from->write_callback); +#ifdef WITH_OOB + assign_svalue(& to->read_oob_callback, + & from->read_oob_callback); + assign_svalue(& to->write_oob_callback, + & from->write_oob_callback); +#endif /* WITH_OOB */ - FD=((struct file_struct *)(o->storage))->fd; - ERRNO=0; - if(FD >=0) files[FD].refs++; + if(IS_ZERO(& from->read_callback)) + { + set_read_callback(to->fd, 0,0); + }else{ + set_read_callback(to->fd, file_read_callback, to); + } + + if(IS_ZERO(& from->write_callback)) + { + set_write_callback(to->fd, 0,0); + }else{ + set_write_callback(to->fd, file_write_callback, to); + } - pop_n_elems(args); - push_int(1); +#ifdef WITH_OOB + if(IS_ZERO(& from->read_oob_callback)) + { + set_read_oob_callback(to->fd, 0,0); + }else{ + set_read_oob_callback(to->fd, file_read_oob_callback, to); + } + + if(IS_ZERO(& from->write_oob_callback)) + { + set_write_oob_callback(to->fd, 0,0); + }else{ + set_write_oob_callback(to->fd, file_write_oob_callback, to); + } +#endif /* WITH_OOB */ + check_internal_reference(to); } static void file_dup2(INT32 args) { - int fd; struct object *o; + struct my_file *fd; if(args < 1) error("Too few arguments to file->dup2()\n"); @@ -1753,18 +1547,16 @@ static void file_dup2(INT32 args) o=sp[-args].u.object; - /* Actually, we allow any object which first inherit is - * /precompiled/file - */ - if(!o->prog || o->prog->inherits[0].prog != file_program) + fd=get_file_storage(o); + + if(!fd) error("Argument 1 to file->dup2() must be a clone of Stdio.File\n"); - fd=((struct file_struct *)(o->storage))->fd; - if(fd < 0) + if(fd->fd < 0) error("File given to dup2 not open.\n"); - if(fd_dup2(FD,fd) < 0) + if(fd_dup2(FD,fd->fd) < 0) { ERRNO=errno; pop_n_elems(args); @@ -1772,52 +1564,36 @@ static void file_dup2(INT32 args) return; } ERRNO=0; - my_set_close_on_exec(fd, fd > 2); - files[fd].open_mode=files[FD].open_mode; + low_dup(o, fd, THIS); + + pop_n_elems(args); + push_int(1); +} - assign_svalue_no_free(& files[fd].read_callback, & THIS->read_callback); - assign_svalue_no_free(& files[fd].write_callback, & THIS->write_callback); -#ifdef WITH_OOB - assign_svalue_no_free(& files[fd].read_oob_callback, - & THIS->read_oob_callback); - assign_svalue_no_free(& files[fd].write_oob_callback, - & THIS->write_oob_callback); -#endif /* WITH_OOB */ - assign_svalue_no_free(& files[fd].close_callback, & THIS->close_callback); - assign_svalue_no_free(& files[fd].id, & THIS->id); +static void file_dup(INT32 args) +{ + int f; + struct object *o; + struct my_file *fd; - if(IS_ZERO(& THIS->read_callback)) - { - set_read_callback(fd, 0,0); - }else{ - set_read_callback(fd, file_read_callback, 0); - } - - if(IS_ZERO(& THIS->write_callback)) - { - set_write_callback(fd, 0,0); - }else{ - set_write_callback(fd, file_write_callback, 0); - } + pop_n_elems(args); -#ifdef WITH_OOB - if(IS_ZERO(& THIS->read_oob_callback)) - { - set_read_oob_callback(fd, 0,0); - }else{ - set_read_oob_callback(fd, file_read_oob_callback, 0); - } - - if(IS_ZERO(& THIS->write_oob_callback)) + if(FD < 0) + error("File not open.\n"); + + + if((f=fd_dup(FD)) < 0) { - set_write_oob_callback(fd, 0,0); - }else{ - set_write_oob_callback(fd, file_write_oob_callback, 0); + ERRNO=errno; + pop_n_elems(args); + push_int(0); + return; } -#endif /* WITH_OOB */ - - pop_n_elems(args); - push_int(1); + o=file_make_object_from_fd(f, THIS->open_mode, THIS->open_mode); + fd=((struct my_file *)(o->storage)); + ERRNO=0; + low_dup(o, fd, THIS); + push_object(o); } /* file->open_socket(int|void port, string|void addr) */ @@ -1825,7 +1601,7 @@ static void file_open_socket(INT32 args) { int fd; - do_close(FD, FILE_READ | FILE_WRITE); + close_fd(); FD=-1; fd=fd_socket(AF_INET, SOCK_STREAM, 0); if(fd >= MAX_OPEN_FILEDESCRIPTORS) @@ -2026,33 +1802,12 @@ static void file_lsh(INT32 args) static void file_create(INT32 args) { - char *s; if(!args || sp[-args].type == T_INT) return; if(sp[-args].type != T_STRING) error("Bad argument 1 to file->create()\n"); - do_close(FD, FILE_READ | FILE_WRITE); - FD=-1; - s=sp[-args].u.string->str; - if(!strcmp(s,"stdin")) - { - FD=0; - files[0].refs++; - } - else if(!strcmp(s,"stdout")) - { - FD=1; - files[1].refs++; - } - else if(!strcmp(s,"stderr")) - { - FD=2; - files[2].refs++; - } - else - { - file_open(args); /* Try opening the file instead. */ - } + close_fd(); + file_open(args); } #ifdef _REENTRANT @@ -2091,9 +1846,9 @@ static void *proxy_thread(void * data) } } + fd_close(p->to); + fd_close(p->from); mt_lock(&interpreter_lock); - do_close(p->to, FILE_READ | FILE_WRITE); - do_close(p->from, FILE_READ | FILE_WRITE); num_threads--; mt_unlock(&interpreter_lock); free((char *)p); @@ -2102,23 +1857,40 @@ static void *proxy_thread(void * data) void file_proxy(INT32 args) { - struct file_struct *f; + struct my_file *f; struct new_thread_data *p; THREAD_T id; check_all_args("Stdio.File->proxy",args, BIT_OBJECT,0); - f=(struct file_struct *)get_storage(sp[-args].u.object, file_program); + f=get_file_storage(sp[-args].u.object); if(!f) error("Bad argument 1 to Stdio.File->proxy, not a Stdio.File object.\n"); p=ALLOC_STRUCT(new_thread_data); - files[p->from=f->fd].refs++; - files[p->to=FD].refs++; + p->from=f->fd; + p->to=FD; + num_threads++; if(th_create_small(&id,proxy_thread,p)) { free((char *)p); error("Failed to create thread.\n"); } + + /* Protect ourself from harm */ + REMOVE_INTERNAL_REFERENCE(f); + f->open_mode=0; + REMOVE_INTERNAL_REFERENCE(THIS); + THIS->open_mode=0; + f->fd=-1; + FD=-1; + set_read_callback(THIS->fd,0,0); + set_write_callback(THIS->fd,0,0); +#ifdef WITH_OOB + set_read_oob_callback(THIS->fd,0,0); + set_write_oob_callback(THIS->fd,0,0); +#endif + check_internal_reference(THIS); + th_destroy(& id); pop_n_elems(args); push_int(0); @@ -2154,7 +1926,7 @@ static struct program * file_lock_key_program; struct file_lock_key_storage { - int fd; + struct my_file *f; #ifdef _REENTRANT struct object *owner; #endif @@ -2184,6 +1956,7 @@ static void low_file_lock(INT32 args, int flags) } o=clone_object(file_lock_key_program,0); + THREADS_ALLOW(); ret=fd_flock(fd, flags); THREADS_DISALLOW(); @@ -2196,7 +1969,7 @@ static void low_file_lock(INT32 args, int flags) push_int(0); }else{ THIS->key=o; - OB2KEY(o)->fd=fd; + OB2KEY(o)->f=THIS; pop_n_elems(args); push_object(o); } @@ -2215,7 +1988,7 @@ static void file_trylock(INT32 args) #define THIS_KEY ((struct file_lock_key_storage *)(fp->current_storage)) static void init_file_lock_key(struct object *o) { - THIS_KEY->fd=-1; + THIS_KEY->f=0; #ifdef _REENTRANT THIS_KEY->owner=thread_id; thread_id->refs++; @@ -2224,12 +1997,12 @@ static void init_file_lock_key(struct object *o) static void exit_file_lock_key(struct object *o) { - if(THIS_KEY->fd != -1) + if(THIS_KEY->f) { - int fd=THIS_KEY->fd; + int fd=THIS_KEY->f->fd; int err; #ifdef DEBUG - if(files[fd].key != o) + if(THIS_KEY->f->key != o) fatal("File lock key is wrong!\n"); #endif @@ -2247,8 +2020,8 @@ static void exit_file_lock_key(struct object *o) THIS_KEY->owner=0; } #endif - files[fd].key=0; - THIS_KEY->fd=-1; + THIS_KEY->f->key=0; + THIS_KEY->f=0; } } @@ -2290,163 +2063,87 @@ void pike_module_exit(void) free_program(file_program); file_program=0; } + if(file_ref_program) + { + free_program(file_ref_program); + file_ref_program=0; + } exit_file_locking(); } -void mark_ids(struct callback *foo, void *bar, void *gazonk) -{ - int e; - for(e=0;e<MAX_OPEN_FILEDESCRIPTORS;e++) - { - int tmp=1; - if(query_read_callback(e)!=file_read_callback) - { - gc_check_svalues( & files[e].read_callback, 1); - gc_check_svalues( & files[e].close_callback, 1); - }else{ -#ifdef DEBUG - debug_gc_xmark_svalues( & files[e].read_callback, 1, "File->read_callback"); - debug_gc_xmark_svalues( & files[e].close_callback, 1, "File->close_callback"); -#endif - tmp=0; - } - - if(query_write_callback(e)!=file_write_callback) - { - gc_check_svalues( & files[e].write_callback, 1); - }else{ -#ifdef DEBUG - debug_gc_xmark_svalues( & files[e].write_callback, 1, "File->write_callback"); -#endif - tmp=0; - } - -#ifdef WITH_OOB - if(query_read_oob_callback(e)!=file_read_oob_callback) - { - gc_check_svalues( & files[e].read_oob_callback, 1); - }else{ -#ifdef DEBUG - debug_gc_xmark_svalues( & files[e].read_oob_callback, 1, "File->read_oob_callback"); -#endif - tmp=0; - } +void init_files_efuns(void); - if(query_write_oob_callback(e)!=file_write_oob_callback) - { - gc_check_svalues( & files[e].write_oob_callback, 1); - }else{ -#ifdef DEBUG - debug_gc_xmark_svalues( & files[e].write_oob_callback, 1, "File->write_callback"); -#endif - tmp=0; - } -#endif /* WITH_OOB */ +#define REF (*((struct object **)(fp->current_storage))) - if(tmp) - { - gc_check_svalues( & files[e].id, 1); - } -#ifdef DEBUG - else - { - debug_gc_xmark_svalues( & files[e].id, 1, "File->id"); - } -#endif - } +#define FILE_FUNC(X,Y,Z) \ +void PIKE_CONCAT(Y,_ref) (INT32 args) {\ + struct object *o=REF; \ + if(!o) error("Stdio.File(): not open.\n"); \ + fp->current_storage=get_storage(o, file_program); \ + if(!fp->current_storage) error("Wrong type of object in Stdio.File->_fd\n"); \ + free_object(fp->current_object); \ + fp->current_object=o; \ + o->refs++; \ + Y(args); \ } -void init_files_efuns(void); +#include "file_functions.h" void pike_module_init(void) { + struct object *o; extern void port_setup_program(void); int e; - - for(e=0;e<MAX_OPEN_FILEDESCRIPTORS;e++) - { - init_fd(e, 0); - files[e].refs=0; - } - - init_fd(0, FILE_READ | fd_query_properties(0,fd_CAN_NONBLOCK)); - init_fd(1, FILE_WRITE | fd_query_properties(1,fd_CAN_NONBLOCK)); - init_fd(2, FILE_WRITE | fd_query_properties(2,fd_CAN_NONBLOCK)); - init_files_efuns(); -#if 0 - start_new_program(); - add_storage(sizeof(struct my_file)); - low_file_program=end_program(); -#endif start_new_program(); - add_storage(sizeof(struct file_struct)); - - add_function("open",file_open,"function(string,string:int)",0); - add_function("close",file_close,"function(string|void:int)",0); - add_function("read",file_read,"function(int|void,int|void:int|string)",0); - add_function("write",file_write,"function(string,void|mixed...:int)",0); -#ifdef WITH_OOB - add_function("read_oob",file_read_oob,"function(int|void,int|void:int|string)",0); - add_function("write_oob",file_write_oob,"function(string,void|mixed...:int)",0); -#endif /* WITH_OOB */ - - add_function("seek",file_seek,"function(int,int|void,int|void:int)",0); - add_function("tell",file_tell,"function(:int)",0); - add_function("stat",file_stat,"function(:int *)",0); - add_function("errno",file_errno,"function(:int)",0); - - add_function("set_close_on_exec",file_set_close_on_exec,"function(int:void)",0); -#ifdef WITH_OOB - add_function("set_nonblocking",file_set_nonblocking,"function(mixed|void,mixed|void,mixed|void,mixed|void,mixed|void:void)",0); -#else /* !WITH_OOB */ - add_function("set_nonblocking",file_set_nonblocking,"function(mixed|void,mixed|void,mixed|void:void)",0); -#endif /* WITH_OOB */ - add_function("set_read_callback",file_set_read_callback,"function(mixed:void)",0); - add_function("set_write_callback",file_set_write_callback,"function(mixed:void)",0); -#ifdef WITH_OOB - add_function("set_read_oob_callback",file_set_read_oob_callback,"function(mixed:void)",0); - add_function("set_write_oob_callback",file_set_write_oob_callback,"function(mixed:void)",0); -#endif /* WITH_OOB */ - add_function("set_close_callback",file_set_close_callback,"function(mixed:void)",0); - - add_function("set_blocking",file_set_blocking,"function(:void)",0); - add_function("set_id",file_set_id,"function(mixed:void)",0); + add_storage(sizeof(struct my_file)); - add_function("query_fd",file_query_fd,"function(:int)",0); - add_function("query_id",file_query_id,"function(:mixed)",0); - add_function("query_read_callback",file_query_read_callback,"function(:mixed)",0); - add_function("query_write_callback",file_query_write_callback,"function(:mixed)",0); +#define FILE_FUNC(X,Y,Z) add_function(X,Y,Z,0); +#include "file_functions.h" + map_variable("_read_callback","mixed",0,OFFSETOF(my_file, read_callback),T_MIXED); + map_variable("_write_callback","mixed",0,OFFSETOF(my_file, write_callback),T_MIXED); #ifdef WITH_OOB - add_function("query_read_oob_callback",file_query_read_oob_callback,"function(:mixed)",0); - add_function("query_write_oob_callback",file_query_write_oob_callback,"function(:mixed)",0); -#endif /* WITH_OOB */ - add_function("query_close_callback",file_query_close_callback,"function(:mixed)",0); - - add_function("dup",file_dup,"function(:object)",0); - add_function("dup2",file_dup2,"function(object:int)",0); - add_function("assign",file_assign,"function(object:int)",0); - add_function("pipe",file_pipe,"function(void|int:object)",0); + map_variable("_read_oob_callback","mixed",0,OFFSETOF(my_file, read_oob_callback),T_MIXED); + map_variable("_write_oob_callback","mixed",0,OFFSETOF(my_file, write_oob_callback),T_MIXED); +#endif - add_function("set_buffer",file_set_buffer,"function(int,string|void:void)",0); - add_function("open_socket",file_open_socket,"function(int|void,string|void:int)",0); - add_function("connect",file_connect,"function(string,int:int)",0); - add_function("query_address",file_query_address,"function(int|void:string)",0); - add_function("create",file_create,"function(void|string,void|string:void)",0); - add_function("`<<",file_lsh,"function(mixed:object)",0); -#ifdef _REENTRANT - add_function("proxy",file_proxy,"function(object:void)",0); -#endif init_file_locking(); set_init_callback(init_file_struct); set_exit_callback(exit_file_struct); - set_gc_mark_callback(gc_mark_file_struct); +#ifdef DEBUG + set_gc_check_callback(gc_mark_file_struct); +#endif file_program=end_program(); - add_program_constant("file",file_program,0); + add_program_constant("Fd",file_program,0); + + o=file_make_object_from_fd(0, FILE_READ , fd_CAN_NONBLOCK); + ((struct my_file *)(o->storage))->flags |= FILE_NO_CLOSE_ON_DESTRUCT; + add_object_constant("_stdin",o,0); + free_object(o); + + o=file_make_object_from_fd(1, FILE_WRITE, fd_CAN_NONBLOCK); + ((struct my_file *)(o->storage))->flags |= FILE_NO_CLOSE_ON_DESTRUCT; + add_object_constant("_stdout",o,0); + free_object(o); + + o=file_make_object_from_fd(2, FILE_WRITE, fd_CAN_NONBLOCK); + ((struct my_file *)(o->storage))->flags |= FILE_NO_CLOSE_ON_DESTRUCT; + add_object_constant("_stderr",o,0); + free_object(o); + + start_new_program(); + add_storage(sizeof(struct object *)); + map_variable("_fd","object",0,0,T_OBJECT); + +#define FILE_FUNC(X,Y,Z) add_function(X,PIKE_CONCAT(Y,_ref),Z,0); +#include "file_functions.h" + + file_ref_program=end_program(); + add_program_constant("Fd_ref",file_ref_program,0); port_setup_program(); @@ -2455,8 +2152,9 @@ void pike_module_init(void) add_integer_constant("PROP_SHUTDOWN",fd_CAN_SHUTDOWN,0); add_integer_constant("PROP_BUFFERED",fd_BUFFERED,0); add_integer_constant("PROP_BIDIRECTIONAL",fd_BIDIRECTIONAL,0); - - add_gc_callback(mark_ids, 0, 0); +#ifdef HAVE_OOB + add_integer_constant("__HAVE_OOB__",1,0); +#endif } /* Used from backend */ @@ -2464,3 +2162,10 @@ int pike_make_pipe(int *fds) { return socketpair(AF_UNIX, SOCK_STREAM, 0, fds); } + +int fd_from_object(struct object *o) +{ + struct my_file *f=get_file_storage(o); + if(!f) return -1; + return f->fd; +} diff --git a/src/modules/files/file.h b/src/modules/files/file.h index 35cab7dfaa1a67d9c9b43ca9afdc63a08fc00623..833ce00321f4fe3834d654ef53d6b2630caeb5cb 100644 --- a/src/modules/files/file.h +++ b/src/modules/files/file.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: file.h,v 1.9 1998/03/28 13:58:04 grubba Exp $ + * $Id: file.h,v 1.10 1998/04/06 04:34:05 hubbe Exp $ */ #ifndef FILE_H @@ -30,44 +30,67 @@ struct my_file { - INT32 refs; short open_mode; - struct svalue id; + short flags; + FD fd; + int my_errno; struct svalue read_callback; struct svalue write_callback; #ifdef WITH_OOB struct svalue read_oob_callback; struct svalue write_oob_callback; #endif /* WITH_OOB */ - struct svalue close_callback; + #ifdef HAVE_FD_FLOCK struct object *key; #endif + struct object *myself; }; extern void get_inet_addr(struct sockaddr_in *addr,char *name); +#define CBFUNCS(X) \ +static void PIKE_CONCAT(file_,X) (int fd, void *data); \ +static void PIKE_CONCAT(file_set_,X) (INT32 args); \ +static void PIKE_CONCAT(file_query_,X) (INT32 args); \ + + /* Prototypes begin here */ -struct file_struct; void my_set_close_on_exec(int fd, int to); void do_set_close_on_exec(void); +CBFUNCS(read_callback) +CBFUNCS(write_callback) + +CBFUNCS(read_oob_callback) +CBFUNCS(write_oob_callback) + +static void file_write(INT32 args); struct object *file_make_object_from_fd(int fd, int mode, int guess); int my_socketpair(int family, int type, int protocol, int sv[2]); -int socketpair(int family, int type, int protocol, int sv[2]); +int socketpair_ultra(int family, int type, int protocol, int sv[2]); +struct new_thread_data; +void file_proxy(INT32 args); +void create_proxy_pipe(struct object *o, int for_reading); +struct file_lock_key_storage; void pike_module_exit(void); void mark_ids(struct callback *foo, void *bar, void *gazonk); void pike_module_init(void); int pike_make_pipe(int *fds); +int fd_from_object(struct object *o); /* Prototypes end here */ #define FILE_READ 0x1000 #define FILE_WRITE 0x2000 #define FILE_APPEND 0x4000 #define FILE_CREATE 0x8000 + #define FILE_TRUNC 0x0100 #define FILE_EXCLUSIVE 0x0200 #define FILE_NONBLOCKING 0x0400 #define FILE_SET_CLOSE_ON_EXEC 0x0800 +/* flags */ +#define FILE_HAS_INTERNAL_REF 0x0001 +#define FILE_NO_CLOSE_ON_DESTRUCT 0x0002 #endif diff --git a/src/modules/files/file_functions.h b/src/modules/files/file_functions.h new file mode 100644 index 0000000000000000000000000000000000000000..9da0e484ecdfec2f3c9794bf3fcd5c9c0f656865 --- /dev/null +++ b/src/modules/files/file_functions.h @@ -0,0 +1,47 @@ + FILE_FUNC("open",file_open,"function(string,string,void|int:int)") + FILE_FUNC("close",file_close,"function(string|void:int)") + FILE_FUNC("read",file_read,"function(int|void,int|void:int|string)") + FILE_FUNC("write",file_write,"function(string,void|mixed...:int)") +#ifdef WITH_OOB + FILE_FUNC("read_oob",file_read_oob,"function(int|void,int|void:int|string)") + FILE_FUNC("write_oob",file_write_oob,"function(string,void|mixed...:int)") +#endif /* WITH_OOB */ + + FILE_FUNC("seek",file_seek,"function(int,int|void,int|void:int)") + FILE_FUNC("tell",file_tell,"function(:int)") + FILE_FUNC("stat",file_stat,"function(:int *)") + FILE_FUNC("errno",file_errno,"function(:int)") + + FILE_FUNC("set_close_on_exec",file_set_close_on_exec,"function(int:void)") + FILE_FUNC("set_nonblocking",file_set_nonblocking,"function(:void)") + + FILE_FUNC("set_read_callback",file_set_read_callback,"function(mixed:void)") + + FILE_FUNC("set_write_callback",file_set_write_callback,"function(mixed:void)") + +#ifdef WITH_OOB + FILE_FUNC("set_read_oob_callback",file_set_read_oob_callback,"function(mixed:void)") + + FILE_FUNC("set_write_oob_callback",file_set_write_oob_callback,"function(mixed:void)") + +#endif /* WITH_OOB */ + FILE_FUNC("set_blocking",file_set_blocking,"function(:void)") + + FILE_FUNC("query_fd",file_query_fd,"function(:int)") + + FILE_FUNC("dup2",file_dup2,"function(object:int)") + FILE_FUNC("dup",file_dup,"function(void:object)") + FILE_FUNC("pipe",file_pipe,"function(void|int:object)") + + FILE_FUNC("set_buffer",file_set_buffer,"function(int,string|void:void)") + FILE_FUNC("open_socket",file_open_socket,"function(int|void,string|void:int)") + FILE_FUNC("connect",file_connect,"function(string,int:int)") + FILE_FUNC("query_address",file_query_address,"function(int|void:string)") + FILE_FUNC("create",file_create,"function(void|string,void|string:void)") + FILE_FUNC("`<<",file_lsh,"function(mixed:object)") + +#ifdef _REENTRANT + FILE_FUNC("proxy",file_proxy,"function(object:void)") +#endif + +#undef FILE_FUNC diff --git a/src/modules/files/socktest.pike b/src/modules/files/socktest.pike index 47235b6290ab2f728c2485e1cc7b190b1ce7d083..623689a9110bb62bc6bf42c86f6ea688d36f6779 100755 --- a/src/modules/files/socktest.pike +++ b/src/modules/files/socktest.pike @@ -1,6 +1,6 @@ #!/usr/local/bin/pike -/* $Id: socktest.pike,v 1.8 1998/01/28 00:33:17 hubbe Exp $ */ +/* $Id: socktest.pike,v 1.9 1998/04/06 04:34:05 hubbe Exp $ */ import Stdio; import String; @@ -9,12 +9,17 @@ import String; #define strerror(X) ("ERRNO = "+(string)(X)) #endif +//int idnum; +//mapping in_cleanup=([]); + class Socket { import Stdio; import String; inherit File; +// int id=idnum++; + object daemon=function_object(backtrace()[-2][2]); int num=daemon->num_running; @@ -26,14 +31,28 @@ class Socket { int input_finished; int output_finished; +// void destroy() +// { +// werror("GONE FISHING %d\n",id); +// werror(master()->describe_backtrace( ({"backtrace:",backtrace() }) ) +"\n"); +// if(in_cleanup[id]) trace(0); +// } + void cleanup() { +// int i=id; +// werror(">>>>>>>>>ENTER CLEANUP %d\n",i); if(input_finished && output_finished) { +// in_cleanup[i]++; daemon->finish(); +// if(!this_object()) +// werror("GURKA %d\n",i); close(); +// in_cleanup[i]--; destruct(this_object()); } +// werror("<<<<<<<<<<EXIT CLEANUP\n",i); } void close_callback() @@ -274,6 +293,7 @@ void finish() exit(0); } } +// werror("FINISHED with FINISH %d\n",_tests); } void accept_callback()