8fb2a22004-11-30Henrik Grubbström (Grubba) /*
e576bb2002-10-11Martin Nilsson || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
aedfb12002-10-09Martin Nilsson 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
5740881998-01-01Fredrik Hübinette (Hubbe) #include "fdlib.h"
5f1c622003-04-30Henrik Grubbström (Grubba) #include "pike_netlib.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "interpret.h" #include "svalue.h" #include "stralloc.h" #include "array.h"
86be732003-05-15Marcus Comstedt #include "mapping.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "object.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "backend.h" #include "fd_control.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "module_support.h"
2402451999-04-01Henrik Grubbström (Grubba) #include "operators.h"
2fe5651999-10-29Fredrik Noring #include "bignum.h"
60ab812002-06-27Martin Nilsson #include "builtin_functions.h"
10dac82004-04-05Martin Stjernholm #include "gc.h"
f010202011-11-16Tobias S. Josefowitz #include "time_stuff.h"
9d3bdd2014-10-01Martin Nilsson #include "buffer.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "file_machine.h" #include "file.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "signal_handler.h" #include "pike_types.h"
07513e1996-10-04Fredrik Hübinette (Hubbe) #include "threads.h"
8524151999-12-14Fredrik Hübinette (Hubbe) #include "program_id.h"
9d1f542017-01-25Henrik Grubbström (Grubba) #include "sprintf.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  #include <sys/stat.h>
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_PARAM_H
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <sys/param.h>
4451331999-04-01Henrik Grubbström (Grubba) #endif /* HAVE_SYS_PARAM_H */
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <errno.h>
334e872003-03-12Marcus Agehall 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <fcntl.h> #include <signal.h>
1f4b351997-05-20Henrik Grubbström (Grubba) 
ca6bd02012-05-01Bill Welliver #ifdef HAVE_SYS_EVENT_H #include <sys/event.h> #endif /* HAVE_SYS_EVENT_H */
7072ec1998-05-01Henrik Grubbström (Grubba) #ifdef HAVE_SYS_FILE_H #include <sys/file.h> #endif /* HAVE_SYS_FILE_H */
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_SOCKET_H # include <sys/socket.h> #endif
6d8ea42005-01-22Martin Nilsson #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif #ifdef HAVE_LINUX_IF_H #include <linux/if.h> #endif
4451331999-04-01Henrik Grubbström (Grubba) #ifdef HAVE_SYS_UIO_H #include <sys/uio.h> #endif /* HAVE_SYS_UIO_H */
50105e2005-04-30Henrik Grubbström (Grubba) #ifdef HAVE_SYS_XATTR_H #include <sys/xattr.h> #endif /* HAVE_SYS_XATTR_H */
9eb34f2011-09-20Henrik Grubbström (Grubba) #ifdef HAVE_AVAILABILITYMACROS_H #include <AvailabilityMacros.h> #endif
5f1c622003-04-30Henrik Grubbström (Grubba) #if defined(HAVE_WINSOCK_H) || defined(HAVE_WINSOCK2_H)
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifndef EWOULDBLOCK #define EWOULDBLOCK WSAEWOULDBLOCK #endif #ifndef EADDRINUSE #define EADDRINUSE WSAEADDRINUSE #endif #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5ad6ac1995-09-25Per Hedbor #ifdef HAVE_SYS_STREAM_H #include <sys/stream.h>
2a15e51996-11-25Fredrik Hübinette (Hubbe)  /* Ugly patch for AIX 3.2 */ #ifdef u #undef u #endif
5ad6ac1995-09-25Per Hedbor #endif #ifdef HAVE_SYS_PROTOSW_H #include <sys/protosw.h> #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_SOCKETVAR_H #include <sys/socketvar.h> #endif
7cfed41998-08-08Henrik Grubbström (Grubba) /* Fix warning on OSF/1 * * NOERROR is defined by both sys/stream.h (-1), and arpa/nameser.h (0), * the latter is included by netdb.h. */ #ifdef NOERROR #undef NOERROR #endif /* NOERROR */
6283791995-09-01Fredrik Hübinette (Hubbe) #ifdef HAVE_NETDB_H
cb22561995-10-11Fredrik Hübinette (Hubbe) #include <netdb.h>
6283791995-09-01Fredrik Hübinette (Hubbe) #endif
f2c5041998-05-22Henrik Grubbström (Grubba) #ifdef HAVE_NET_NETDB_H #include <net/netdb.h> #endif /* HAVE_NET_NETDB_H */
6283791995-09-01Fredrik Hübinette (Hubbe) 
c8f8112014-08-29Chris Angelico #ifdef HAVE_NETINET_TCP_H #include <netinet/tcp.h> #endif
bdfb861997-12-22Fredrik Hübinette (Hubbe) #undef THIS
5923b12000-07-06Fredrik Hübinette (Hubbe) #define THIS ((struct my_file *)(Pike_fp->current_storage))
10dac82004-04-05Martin Stjernholm #define FD (THIS->box.fd)
a1ef721998-04-05Fredrik Hübinette (Hubbe) #define ERRNO (THIS->my_errno)
4107532010-02-23Stephen R. van den Berg #define READ_BUFFER 8192 #define DIRECT_BUFSIZE (64*1024) #define SMALL_NETBUF 2048
3e11ee2010-02-18Stephen R. van den Berg #define INUSE_BUSYWAIT_DELAY 0.01 #define INUSE_TIMEOUT 0.1
5267b71995-08-09Fredrik Hübinette (Hubbe) 
67af2e2000-12-16Marcus Comstedt /* Don't try to use socketpair() on AmigaOS, socketpair_ultra works better */ #ifdef __amigaos__ #undef HAVE_SOCKETPAIR #endif
89fdb32010-11-19Henrik Grubbström (Grubba) #ifdef UNIX_SOCKETS_WORK_WITH_SHUTDOWN #undef UNIX_SOCKET_CAPABILITIES #define UNIX_SOCKET_CAPABILITIES (fd_INTERPROCESSABLE | fd_BIDIRECTIONAL | fd_CAN_NONBLOCK | fd_CAN_SHUTDOWN | fd_SEND_FD) #endif
a6cba12014-10-28Henrik Grubbström (Grubba) #ifndef HAVE_DIRFD #ifdef HAVE_DIR_DD_FD #define dirfd(dir__) (((DIR*)dir__)->dd_fd) #define HAVE_DIRFD #elif defined(HAVE_DIR_D_FD) #define dirfd(dir__) (((DIR*)dir__)->d_fd) #define HAVE_DIRFD #endif #endif
04f4cd2014-05-12Arne Goedeke /* * gcc with -O3 generates very bloated code for the functions in this file. One rather extreme example * is file_open, which ends up having 32 call sites of open(2). */ #ifdef __GNUC__ #pragma GCC optimize "-Os" #endif
0879262000-10-08Henrik Grubbström (Grubba) /* #define SOCKETPAIR_DEBUG */
61e49f1999-04-20Henrik Grubbström (Grubba) struct program *file_program; struct program *file_ref_program;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
fe749b2013-06-17Martin Nilsson /*! @module Stdio
9c052f2001-02-15Henrik Grubbström (Grubba)  */
29d1c02016-08-05Henrik Grubbström (Grubba) /*! @enum FileModeFlags *! *! File mode flags returned by @[Fd()->mode()]. */ /*! @decl constant FILE_READ = 0x1000 *! File open for reading. */ /*! @decl constant FILE_WRITE = 0x2000 *! File open for writing. */ /*! @decl constant FILE_APPEND = 0x4000 *! File open for appending. */ /*! @decl constant FILE_CREATE = 0x8000 *! Create a new file if it didn't exist earlier. */ /*! @decl constant FILE_TRUNC = 0x0100 *! Truncate the file on open. */ /*! @decl constant FILE_EXCLUSIVE = 0x0200 *! Exclusive access to the file. */ /*! @decl constant FILE_NONBLOCKING = 0x0400 *! File opened in nonblocking mode. */ /*! @endenum FileModeFlags */ /*! @enum FilePropertyFlags *! *! File properties for use with eg @[Fd()->pipe()], *! and returned by eg @[Fd()->mode()]. */ /*! @decl constant PROP_SEND_FD = 0x0040 *! File is capable of sending open file descriptors. */ /*! @decl constant PROP_BIDIRECTIONAL = 0x0010 *! File supports both sending and receiving. */ /*! @decl constant PROP_BUFFERED = 0x0008 *! File has internal buffering. */ /*! @decl constant PROP_SHUTDOWN = 0x0004 *! File supports unidirectional close. */ /*! @decl constant PROP_NONBLOCK = 0x0002 *! File supports nonblocking operation. */ /*! @decl constant PROP_IPC = 0x0001 *! File can be used for interprocess communication. */ /*! @endenum FilePropertyFlags */
1053be2001-11-22Martin Nilsson /*! @class Fd_ref *! *! Proxy class that contains stub functions *! that call the corresponding functions in *! @[Fd]. *!
f736b62012-05-12Henrik Grubbström (Grubba)  *! Used by @[Stdio.File].
22c9eb2013-06-14Henrik Grubbström (Grubba)  *! *! @note *! This is not the class you want. Use @[Stdio.File] and friends instead. *! *! @seealso *! @[Stdio.File], @[Stdio.FILE], @[_Stdio.Fd]
1053be2001-11-22Martin Nilsson  */ /*! @decl Fd _fd *! Object to which called functions are relayed. */
22c9eb2013-06-14Henrik Grubbström (Grubba) /*! @decl inherit Fd *! *! Fake inherit to propagate the documentation *! from @[_Stdio.Fd]. */
1053be2001-11-22Martin Nilsson /*! @endclass */ /*! @class Fd *!
22c9eb2013-06-14Henrik Grubbström (Grubba)  *! Low level I/O operations. *! *! @note *! This is not the class you want. Use @[Stdio.File] and friends instead. *! *! @seealso *! @[Stdio.File], @[Stdio.FILE], @[_Stdio.Fd_ref]
9c052f2001-02-15Henrik Grubbström (Grubba)  */
da7e5d2009-02-23Henrik Grubbström (Grubba) /*! @decl Fd fd_factory() *! *! Factory creating @[Stdio.Fd] objects. *! *! This function is called by @[openat()], @[pipe()], @[dup()] *! and other functions creating new file objects. *! *! The default implementation calls @expr{object_program(this_object())()@} *! to create the new object, and returns the @[Fd] inherit in it. *! *! @note *! Note that this function must return the @[Fd] inherit in the object. *! *! @seealso *! @[Stdio.Port()->fd_factory()], @[openat()], @[pipe()] */ static int fd_fd_factory_fun_num = -1; static void fd_fd_factory(INT32 args) { pop_n_elems(args); push_object_inherit(clone_object_from_object(Pike_fp->current_object, 0), Pike_fp->context - Pike_fp->current_program->inherits); }
c592502012-05-12Henrik Grubbström (Grubba) /*! @decl object(Fd) `_fd() *! *! Getter for the Fd object.
da7e5d2009-02-23Henrik Grubbström (Grubba)  */ static void fd_backtick__fd(INT32 args) { pop_n_elems(args); ref_push_object_inherit(Pike_fp->current_object, Pike_fp->context - Pike_fp->current_program->inherits); }
64129c2014-09-28Henrik Grubbström (Grubba) /*! @decl protected int(0..) _errno *! *! Variable containing the internal value returned by @[errno()]. *! *! @seealso *! @[errno()]
91c5502013-06-14Martin Nilsson  */
c592502012-05-12Henrik Grubbström (Grubba) 
64129c2014-09-28Henrik Grubbström (Grubba) /*! @decl mixed _read_callback *! @decl mixed _write_callback *! @decl mixed _read_oob_callback *! @decl mixed _write_oob_callback *! @decl mixed _fs_event_callback *! *! Callback functions installed by @[Stdio.File()->set_callbacks()] et al.
1261b92002-11-23Martin Stjernholm  */
a1ef721998-04-05Fredrik Hübinette (Hubbe) static struct my_file *get_file_storage(struct object *o)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
a1ef721998-04-05Fredrik Hübinette (Hubbe)  struct my_file *f;
e0d7da2011-09-07Henrik Grubbström (Grubba)  struct svalue *sval; struct object *ob;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(o->prog == file_program)
292cfe2009-02-24Henrik Grubbström (Grubba)  return ((struct my_file *) (o->storage + file_program->inherits->storage_offset));
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
13b5ed2014-05-26Per Hedbor  if((f=get_storage(o,file_program)))
a1ef721998-04-05Fredrik Hübinette (Hubbe)  return f;
13b5ed2014-05-26Per Hedbor  if((sval=get_storage(o,file_ref_program))) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*sval) == PIKE_T_OBJECT) {
e0d7da2011-09-07Henrik Grubbström (Grubba)  ob = sval->u.object; /* FIXME: Use the subtype information! */
13b5ed2014-05-26Per Hedbor  if(ob && (f=get_storage(ob, file_program)))
a1ef721998-04-05Fredrik Hübinette (Hubbe)  return f;
e0d7da2011-09-07Henrik Grubbström (Grubba)  } }
ee71702000-01-30Per Hedbor 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
10dac82004-04-05Martin Stjernholm static void debug_check_internals (struct my_file *f) { size_t ev;
76f7462014-05-26Martin Nilsson  if (f->box.ref_obj->prog && file_program && !get_storage(f->box.ref_obj,file_program) )
10dac82004-04-05Martin Stjernholm  Pike_fatal ("ref_obj is not a file object.\n"); for (ev = 0; ev < NELEM (f->event_cbs); ev++)
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(f->event_cbs[ev]) == PIKE_T_INT &&
10dac82004-04-05Martin Stjernholm  f->box.backend && f->box.events & (1 << ev))
2d76f22005-05-20Martin Stjernholm  Pike_fatal ("Got event flag but no callback for event %"PRINTSIZET"d.\n", ev);
10dac82004-04-05Martin Stjernholm }
a1ef721998-04-05Fredrik Hübinette (Hubbe) #else
10dac82004-04-05Martin Stjernholm #define debug_check_internals(f) do {} while (0)
a1ef721998-04-05Fredrik Hübinette (Hubbe) #endif
f0d73c1995-11-04Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm #define ADD_FD_EVENTS(F, EVENTS) do { \ struct my_file *f_ = (F); \ if (!f_->box.backend) \ INIT_FD_CALLBACK_BOX (&f_->box, default_backend, f_->box.ref_obj, \
ca6bd02012-05-01Bill Welliver  f_->box.fd, (EVENTS), got_fd_event, 0); \ else \ set_fd_callback_events (&f_->box, f_->box.events | (EVENTS), 0); \ } while (0) #define ADD_FD_EVENTS2(F, EVENTS, FFLAGS) do { \ struct my_file *f_ = (F); \ if (!f_->box.backend) \ INIT_FD_CALLBACK_BOX (&f_->box, default_backend, f_->box.ref_obj, \ f_->box.fd, (EVENTS), got_fd_event, FFLAGS); \
10dac82004-04-05Martin Stjernholm  else \
ca6bd02012-05-01Bill Welliver  set_fd_callback_events (&f_->box, f_->box.events | (EVENTS), FFLAGS); \
10dac82004-04-05Martin Stjernholm  } while (0)
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm /* Note: The file object might be freed after this. */ #define SUB_FD_EVENTS(F, EVENTS) do { \ struct my_file *f_ = (F); \ if (f_->box.backend) \
ca6bd02012-05-01Bill Welliver  set_fd_callback_events (&f_->box, f_->box.events & ~(EVENTS), 0); \ } while (0) #define SUB_FD_EVENTS2(F, EVENTS, FLAGS) do { \ struct my_file *f_ = (F); \ if (f_->box.backend) \ set_fd_callback_events (&f_->box, f_->box.events & ~(EVENTS), FLAGS); \
10dac82004-04-05Martin Stjernholm  } while (0) static int got_fd_event (struct fd_callback_box *box, int event)
a1ef721998-04-05Fredrik Hübinette (Hubbe) {
10dac82004-04-05Martin Stjernholm  struct my_file *f = (struct my_file *) box; struct svalue *cb = &f->event_cbs[event];
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  f->my_errno = errno; /* Propagate backend setting. */ /* The event is turned on again in the read and write functions. */
ca6bd02012-05-01Bill Welliver  if(event != PIKE_FD_FS_EVENT) SUB_FD_EVENTS (f, 1 << event);
10dac82004-04-05Martin Stjernholm  check_destructed (cb); if (!UNSAFE_IS_ZERO (cb)) {
ca6bd02012-05-01Bill Welliver  if(event == PIKE_FD_FS_EVENT) push_int(box->rflags); apply_svalue (cb, event == PIKE_FD_FS_EVENT);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) == PIKE_T_INT && Pike_sp[-1].u.integer == -1) {
10dac82004-04-05Martin Stjernholm  pop_stack(); return -1; } pop_stack(); } return 0;
a1ef721998-04-05Fredrik Hübinette (Hubbe) }
d4828c1997-07-17Fredrik Hübinette (Hubbe) 
9ea5be2011-09-07Henrik Grubbström (Grubba) static int fd_receive_fd_fun_num;
41d7dc2007-05-20Henrik Grubbström (Grubba) static void init_fd(int fd, int open_mode, int flags)
a1ef721998-04-05Fredrik Hübinette (Hubbe) {
10dac82004-04-05Martin Stjernholm  size_t ev;
9ea5be2011-09-07Henrik Grubbström (Grubba)  struct identifier *i;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  ERRNO=0;
9ea5be2011-09-07Henrik Grubbström (Grubba)  i = ID_FROM_INT(Pike_fp->current_object->prog, fd_receive_fd_fun_num + Pike_fp->context->identifier_level); if (((i->identifier_flags & IDENTIFIER_TYPE_MASK) == IDENTIFIER_PIKE_FUNCTION) && (i->func.offset != -1)) { /* receive_fd() is not a prototype. */ flags |= FILE_HAVE_RECV_FD; }
41d7dc2007-05-20Henrik Grubbström (Grubba)  THIS->flags=flags;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  THIS->open_mode=open_mode;
10dac82004-04-05Martin Stjernholm  for (ev = 0; ev < NELEM (THIS->event_cbs); ev++) {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(THIS->event_cbs[ev], PIKE_T_INT, NUMBER_NUMBER, integer, 0);
10dac82004-04-05Martin Stjernholm  }
26dbd42010-11-21Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD
f126b62010-11-19Henrik Grubbström (Grubba)  THIS->fd_info = NULL;
26dbd42010-11-21Henrik Grubbström (Grubba) #endif
ee71702000-01-30Per Hedbor #if defined(HAVE_FD_FLOCK) || defined(HAVE_FD_LOCKF)
a1ef721998-04-05Fredrik Hübinette (Hubbe)  THIS->key=0; #endif
a0590e2003-10-28Martin Stjernholm #ifdef PIKE_DEBUG
41d7dc2007-05-20Henrik Grubbström (Grubba)  /* Don't cause a fatal when opening fds by number * if the fd belongs to a backend... */ if ((fd >= 0) && !(flags & FILE_NOT_OPENED)) debug_check_fd_not_in_use (fd);
a0590e2003-10-28Martin Stjernholm #endif
60208c2008-06-12Henrik Grubbström (Grubba)  change_fd_for_box(&THIS->box, fd);
a1ef721998-04-05Fredrik Hübinette (Hubbe) }
f126b62010-11-19Henrik Grubbström (Grubba) /* Use ptrdiff_t for the fd since we're passed a void * and should * read it as an integer of the same size. */ static void do_close_fd(ptrdiff_t fd) { int ret; if (fd < 0) return; do { ret = fd_close(fd); } while ((ret == -1) && (errno == EINTR)); }
26dbd42010-11-21Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD
f126b62010-11-19Henrik Grubbström (Grubba) /* Close the queued fds in fd_info, either due to them being successfully * sent, or due to the connection being closed. */ static void do_close_fd_info(int *fd_info) { int num_fds = fd_info[1]; int *fds = fd_info + 2; while (num_fds) { do_close_fd(fds[--num_fds]); #ifdef PIKE_DEBUG fds[num_fds] = -1; #endif } fd_info[1] = 0; } /* Restore THIS->fd_info that was removed during the call to writev_fds(). */ static void restore_fd_info(int *fd_info) { int *other_fd_info; if ((other_fd_info = THIS->fd_info)) { /* Someone added fds to send when we weren't looking... */ int i, j, cnt; int num_fds = fd_info[1] + other_fd_info[1] + 2;
f96c7e2011-09-20Henrik Grubbström (Grubba)  #ifdef PIKE_DEBUG if (other_fd_info == fd_info) { Pike_fatal("restore_fd_info: Double restore!\n"); } #endif
f126b62010-11-19Henrik Grubbström (Grubba)  if (num_fds <= fd_info[0]) { cnt = other_fd_info[1] + 2; for (i = 2; i < cnt; i++) { fd_info[fd_info[1] + i] = other_fd_info[i]; } fd_info[1] += cnt-2; free(other_fd_info); } else if (num_fds <= other_fd_info[0]) { /* Move the other fds so that we can prepend the old ones. */ cnt = fd_info[1] + 2; for(i = other_fd_info[1] + 1, j = num_fds-1; j >= cnt; i--, j--) { other_fd_info[j] = other_fd_info[i]; } for(i = 2; i < cnt; i++) { other_fd_info[i] = fd_info[i]; } other_fd_info[1] = num_fds; free(fd_info); fd_info = other_fd_info; } else {
3a1a3b2014-11-03Martin Nilsson  int *new_fd_info = calloc(num_fds, sizeof(int));
f126b62010-11-19Henrik Grubbström (Grubba)  if (!new_fd_info) { /* FIXME: Huston, we have a problem... */ Pike_fatal("Out of memory in send_fd().\n"); } else { new_fd_info[0] = num_fds; new_fd_info[1] = num_fds - 2; cnt = fd_info[1] + 2; for (i = 2; i < cnt; i++) { new_fd_info[i] = fd_info[i]; } free(fd_info); fd_info = new_fd_info; new_fd_info += i; cnt = other_fd_info[1] + 2; for (i = 2; i < cnt; i++) { new_fd_info[i] = other_fd_info[i]; } free(other_fd_info); } } } THIS->fd_info = fd_info; }
26dbd42010-11-21Henrik Grubbström (Grubba) #endif
f126b62010-11-19Henrik Grubbström (Grubba) 
a1ef721998-04-05Fredrik Hübinette (Hubbe) static void free_fd_stuff(void) {
10dac82004-04-05Martin Stjernholm  size_t ev;
ee71702000-01-30Per Hedbor #if defined(HAVE_FD_FLOCK) || defined(HAVE_FD_LOCKF)
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(THIS->key) { destruct(THIS->key); THIS->key=0; }
d386e61998-03-20Fredrik Hübinette (Hubbe) #endif
10dac82004-04-05Martin Stjernholm 
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (THIS->fd_info) do_close_fd_info(THIS->fd_info); #endif
10dac82004-04-05Martin Stjernholm  for (ev = 0; ev < NELEM (THIS->event_cbs); ev++) { free_svalue(& THIS->event_cbs[ev]);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(THIS->event_cbs[ev], PIKE_T_INT, NUMBER_NUMBER, integer, 0);
10dac82004-04-05Martin Stjernholm  }
a1ef721998-04-05Fredrik Hübinette (Hubbe) }
ba3d5c2001-09-27Fredrik Hübinette (Hubbe) static void close_fd_quietly(void) { int fd=FD; if(fd<0) return;
10dac82004-04-05Martin Stjernholm  free_fd_stuff();
0242472011-01-26Martin Stjernholm  SUB_FD_EVENTS (THIS, ~0);
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&THIS->box, -1);
ba3d5c2001-09-27Fredrik Hübinette (Hubbe)  while(1) {
700dac2002-02-05Martin Stjernholm  int i, e;
ba3d5c2001-09-27Fredrik Hübinette (Hubbe)  THREADS_ALLOW_UID(); i=fd_close(fd);
ae39322003-09-30Martin Stjernholm  e=errno;
ba3d5c2001-09-27Fredrik Hübinette (Hubbe)  THREADS_DISALLOW_UID();
700dac2002-02-05Martin Stjernholm  check_threads_etc();
ba3d5c2001-09-27Fredrik Hübinette (Hubbe)  if(i < 0) {
700dac2002-02-05Martin Stjernholm  switch(e)
ba3d5c2001-09-27Fredrik Hübinette (Hubbe)  {
10dac82004-04-05Martin Stjernholm  default: { JMP_BUF jmp; if (SETJMP (jmp)) call_handle_error(); else { ERRNO=errno=e; change_fd_for_box (&THIS->box, fd); push_int(e); f_strerror(1);
9606eb2004-11-12Henrik Grubbström (Grubba)  Pike_error("Failed to close file: %S\n", Pike_sp[-1].u.string);
10dac82004-04-05Martin Stjernholm  } UNSETJMP (jmp);
ba3d5c2001-09-27Fredrik Hübinette (Hubbe)  break; } case EBADF:
b67d592008-08-04Martin Stjernholm  break;
ba3d5c2001-09-27Fredrik Hübinette (Hubbe) #ifdef SOLARIS /* It's actually OK. This is a bug in Solaris 8. */ case EAGAIN: break; #endif case EINTR:
700dac2002-02-05Martin Stjernholm  continue;
ba3d5c2001-09-27Fredrik Hübinette (Hubbe)  } } break; } }
10dac82004-04-05Martin Stjernholm static void close_fd(void)
a1ef721998-04-05Fredrik Hübinette (Hubbe) { int fd=FD; if(fd<0) return;
10dac82004-04-05Martin Stjernholm  free_fd_stuff();
0242472011-01-26Martin Stjernholm  SUB_FD_EVENTS (THIS, ~0);
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&THIS->box, -1);
3bfc962003-10-15Henrik Grubbström (Grubba) 
10dac82004-04-05Martin Stjernholm  if ( (THIS->flags & FILE_NOT_OPENED) ) return;
d386e61998-03-20Fredrik Hübinette (Hubbe) 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  while(1) {
700dac2002-02-05Martin Stjernholm  int i, e;
52b7eb1998-06-25Henrik Grubbström (Grubba)  THREADS_ALLOW_UID();
a1ef721998-04-05Fredrik Hübinette (Hubbe)  i=fd_close(fd);
ae39322003-09-30Martin Stjernholm  e=errno;
52b7eb1998-06-25Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID();
ee71702000-01-30Per Hedbor 
700dac2002-02-05Martin Stjernholm  check_threads_etc();
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(i < 0)
d3ef711995-11-02Fredrik Hübinette (Hubbe)  {
700dac2002-02-05Martin Stjernholm  switch(e)
d3ef711995-11-02Fredrik Hübinette (Hubbe)  {
ad16f41996-02-18Fredrik Hübinette (Hubbe)  default:
ae39322003-09-30Martin Stjernholm  ERRNO=errno=e;
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&THIS->box, fd);
700dac2002-02-05Martin Stjernholm  push_int(e);
6c1b012000-08-22Martin Stjernholm  f_strerror(1);
9606eb2004-11-12Henrik Grubbström (Grubba)  Pike_error("Failed to close file: %S\n", Pike_sp[-1].u.string);
19a2be2001-01-23Xavier Beaudouin  break;
ee71702000-01-30Per Hedbor 
ad16f41996-02-18Fredrik Hübinette (Hubbe)  case EBADF:
a4a1722000-12-05Per Hedbor  Pike_error("Internal error: Closing a non-active file descriptor %d.\n",fd);
19a2be2001-01-23Xavier Beaudouin  break;
a246f32000-09-18Per Hedbor #ifdef SOLARIS
19a2be2001-01-23Xavier Beaudouin  /* It's actually OK. This is a bug in Solaris 8. */
a246f32000-09-18Per Hedbor  case EAGAIN: break; #endif
ee71702000-01-30Per Hedbor 
a246f32000-09-18Per Hedbor  case EINTR:
700dac2002-02-05Martin Stjernholm  continue;
d3ef711995-11-02Fredrik Hübinette (Hubbe)  } }
a1ef721998-04-05Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
a1ef721998-04-05Fredrik Hübinette (Hubbe) }
c657d01997-01-29Fredrik Hübinette (Hubbe) void my_set_close_on_exec(int fd, int to) {
31b3b91998-04-17Fredrik Hübinette (Hubbe)  set_close_on_exec(fd, to);
c657d01997-01-29Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) void do_set_close_on_exec(void)
c657d01997-01-29Fredrik Hübinette (Hubbe) { }
f0d73c1995-11-04Fredrik Hübinette (Hubbe) /* Parse "rw" to internal flags */
5267b71995-08-09Fredrik Hübinette (Hubbe) static int parse(char *a) { int ret; ret=0; while(1) { switch(*(a++)) { case 0: return ret; case 'r': case 'R': ret|=FILE_READ; break; case 'w': case 'W': ret|=FILE_WRITE;
ee71702000-01-30Per Hedbor  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case 'a': case 'A': ret|=FILE_APPEND; break; case 'c': case 'C': ret|=FILE_CREATE; break; case 't': case 'T': ret|=FILE_TRUNC; break; case 'x': case 'X': ret|=FILE_EXCLUSIVE; break; } } }
f0d73c1995-11-04Fredrik Hübinette (Hubbe) /* Translate internal flags to open(2) modes */
5267b71995-08-09Fredrik Hübinette (Hubbe) static int map(int flags) { int ret; ret=0; switch(flags & (FILE_READ|FILE_WRITE)) {
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  case FILE_READ: ret=fd_RDONLY; break; case FILE_WRITE: ret=fd_WRONLY; break; case FILE_READ | FILE_WRITE: ret=fd_RDWR; break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  if(flags & FILE_APPEND) ret|=fd_APPEND; if(flags & FILE_CREATE) ret|=fd_CREAT; if(flags & FILE_TRUNC) ret|=fd_TRUNC; if(flags & FILE_EXCLUSIVE) ret|=fd_EXCL;
72c4222003-11-26Henrik Grubbström (Grubba)  ret |= fd_LARGEFILE;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; }
2b10c61996-12-03Fredrik Hübinette (Hubbe) static struct pike_string *do_read(int fd, INT32 r, int all,
64129c2014-09-28Henrik Grubbström (Grubba)  INT_TYPE *err)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
c0b9c72016-11-10Arne Goedeke  size_t bytes = r; struct byte_buffer buf = BUFFER_INIT();
817d522017-01-01Arne Goedeke  int e = 0;
cb22561995-10-11Fredrik Hübinette (Hubbe) 
0882252017-01-07Arne Goedeke  buffer_set_flags(&buf, BUFFER_GROW_EXACT);
c0b9c72016-11-10Arne Goedeke  while (bytes) { size_t len = MINIMUM(DIRECT_BUFSIZE, bytes); ptrdiff_t i;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
817d522017-01-01Arne Goedeke  /* make space for exactly len bytes plus the terminating null byte */
0882252017-01-07Arne Goedeke  if (UNLIKELY(!buffer_ensure_space_nothrow(&buf, len+1))) {
c0b9c72016-11-10Arne Goedeke  e = ENOMEM; break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
e11a532017-04-23Arne Goedeke  THREADS_ALLOW();
c0b9c72016-11-10Arne Goedeke  i = fd_read(fd, buffer_alloc_unsafe(&buf, len), len);
4107532010-02-23Stephen R. van den Berg 
e11a532017-04-23Arne Goedeke  THREADS_DISALLOW();
c0b9c72016-11-10Arne Goedeke  if (LIKELY(i >= 0)) { if ((size_t)i < len) buffer_remove(&buf, len - i); bytes -= i; if (!i || !all) break; } else { e=errno;
bcb8072017-04-24Henrik Grubbström (Grubba)  buffer_remove(&buf, len); check_threads_etc();
c0b9c72016-11-10Arne Goedeke  if (e == EINTR) { e = 0; continue; } break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
c0b9c72016-11-10Arne Goedeke  }
4107532010-02-23Stephen R. van den Berg 
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
bcb8072017-04-24Henrik Grubbström (Grubba)  if (e && !buffer_content_length(&buf)) { buffer_free(&buf);
c0b9c72016-11-10Arne Goedeke  *err = e; return NULL;
2b10c61996-12-03Fredrik Hübinette (Hubbe)  }
c0b9c72016-11-10Arne Goedeke  if(!SAFE_IS_ZERO(& THIS->event_cbs[PIKE_FD_READ])) ADD_FD_EVENTS (THIS, PIKE_BIT_FD_READ); return buffer_finish_pike_string(&buf);
2b10c61996-12-03Fredrik Hübinette (Hubbe) }
89fdb32010-11-19Henrik Grubbström (Grubba) /* This function is used to analyse anonymous fds, so that * my_file->open_mode can be set properly. */ static int low_fd_query_properties(int fd) { struct stat st; PIKE_SOCKADDR addr; ACCEPT_SIZE_T len; int i; int orig_errno = errno; int open_mode = 0; #ifndef __NT__ do { i = fcntl(fd, F_GETFL); } while ((i == -1) && (errno == EINTR)); if (i == -1) { /* Probably EBADF. */ errno = orig_errno; return 0; } switch(i & fd_ACCMODE) { case fd_RDONLY: open_mode = FILE_READ; break; case fd_WRONLY: open_mode = FILE_WRITE; break; case fd_RDWR: open_mode = FILE_READ | FILE_WRITE; break; } if (i & fd_APPEND) open_mode |= FILE_APPEND; if (i & fd_CREAT) open_mode |= FILE_CREATE; if (i & fd_TRUNC) open_mode |= FILE_TRUNC; if (i & fd_EXCL) open_mode |= FILE_EXCLUSIVE; #ifdef O_NONBLOCK if (i & O_NONBLOCK) open_mode |= FILE_NONBLOCKING; #elif defined(O_NDELAY) if (i & O_NDELAY) open_mode |= FILE_NONBLOCKING; #endif #endif /* !__NT__ */ do { i = fd_fstat(fd, &st); } while ((i < 0) && (errno == EINTR)); errno = orig_errno; if (i < 0) return open_mode|FILE_CAPABILITIES; switch(st.st_mode & S_IFMT) { default: return open_mode | FILE_CAPABILITIES;
b0ebd12013-08-14Marcus Comstedt #ifdef PIPE_CAPABILITIES
89fdb32010-11-19Henrik Grubbström (Grubba)  case S_IFIFO: return open_mode | PIPE_CAPABILITIES;
b0ebd12013-08-14Marcus Comstedt #endif
89fdb32010-11-19Henrik Grubbström (Grubba)  case S_IFSOCK: break; } addr.sa.sa_family = AF_INET; /* Paranoia, since we don't look at len. */ do { len = sizeof(addr); i = fd_getsockname(fd, &addr.sa, &len); } while ((i < 0) && (errno == EINTR)); errno = orig_errno; if (i < 0) { /* Not a socket (anymore?). */ return open_mode | FILE_CAPABILITIES; } else { switch (addr.sa.sa_family) {
58712c2011-03-23Henrik Grubbström (Grubba)  /* NB: NT defines AF_UNIX (but doesn't support it). */ #if defined(AF_UNIX) && (AF_UNIX != AF_INET) && !defined(__NT__)
89fdb32010-11-19Henrik Grubbström (Grubba)  case AF_UNIX: return open_mode | UNIX_SOCKET_CAPABILITIES; #endif default: /* FIXME: Consider detecting ports? */ return open_mode | SOCKET_CAPABILITIES; } } }
f126b62010-11-19Henrik Grubbström (Grubba) /*! @decl void receive_fd(Stdio.Fd fd) *! *! Remote file descriptor reception handler. *! *! @param fd *! File descriptor received from the remote end of a @[pipe()]. *! This object has been created by @[fd_factory()]. *! *! This function is called from @[read()] when a remote file *! descriptor has been received over a @[PROP_SEND_FD] *! capable @[pipe()]. *! *! The default implementation is just a prototype. *! *! Overload this function to enable reception of *! remote file descriptors. *! *! @note *! The capability of sending and receiving remote file *! descriptors is only available on some operating systems. *! This capability is indicated by the precence of @[__HAVE_SEND_FD__]. *! *! @seealso *! @[send_fd()], @[read()], @[fd_factory()], @[__HAVE_SEND_FD__] */ #ifdef HAVE_PIKE_SEND_FD static void receive_fds(int *fds, size_t num_fds) {
86eae42014-08-26Per Hedbor  volatile size_t i;
f126b62010-11-19Henrik Grubbström (Grubba)  for (i = 0; i < num_fds; i++) { int fd = fds[i]; if (fd >= 0) { JMP_BUF jmp; if (SETJMP(jmp)) call_handle_error(); else { push_new_fd_object(fd_fd_factory_fun_num, fd, low_fd_query_properties(fd), 0); apply_current(fd_receive_fd_fun_num, 1); pop_stack(); } UNSETJMP(jmp); } } } static void check_message(struct msghdr *msg) { #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL struct cmsghdr *cmsg;
9eb34f2011-09-20Henrik Grubbström (Grubba) #if defined(MAC_OS_X_VERSION_10_0) && !defined(MAC_OS_X_VERSION_10_6) /* The CMSG_DATA() and CMSG_LEN() macros are broken on MacOS X 10.5 * and earlier for 64-bit ABI, where it adds extra padding between * the struct cmsghdr and the data, while the kernel doesn't... * * The macros seem to be fixed in the 10.6 header files. * * /grubba 2011-09-19. */ #undef CMSG_DATA #define CMSG_DATA(X) ((void *)((X) + 1)) #undef CMSG_LEN #define CMSG_LEN(X) (sizeof(struct cmsghdr) + (X)) #endif
f126b62010-11-19Henrik Grubbström (Grubba)  for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) { receive_fds((int *)CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0))/sizeof(int)); } } #else
7589632011-01-26Henrik Grubbström (Grubba)  receive_fds((int *)msg->msg_accrights, msg->msg_accrightslen/sizeof(int));
f126b62010-11-19Henrik Grubbström (Grubba) #endif }
7589632011-01-26Henrik Grubbström (Grubba) #ifndef HAVE_STRUCT_MSGHDR_MSG_CONTROL /* BSD */ #define CMSG_LEN(x) (x) #endif
f126b62010-11-19Henrik Grubbström (Grubba) static struct pike_string *do_recvmsg(INT32 r, int all) { ONERROR ebuf; ptrdiff_t bytes_read = 0, i; int fd = FD; struct { struct msghdr msg; struct iovec iov; char cmsgbuf[CMSG_LEN(sizeof(int)*128)]; } message; ERRNO=0; message.msg.msg_name = NULL; message.msg.msg_namelen = 0; message.msg.msg_iov = &message.iov; message.msg.msg_iovlen = 1;
7589632011-01-26Henrik Grubbström (Grubba) #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL /* XPG 4.2 */
f126b62010-11-19Henrik Grubbström (Grubba)  message.msg.msg_flags = 0;
7589632011-01-26Henrik Grubbström (Grubba) #endif
f126b62010-11-19Henrik Grubbström (Grubba)  { /* For some reason, 8k seems to work faster than 64k. * (4k seems to be about 2% faster than 8k when using linux though) * /Hubbe (Per pointed it out to me..) */
c9ec4d2017-01-01Arne Goedeke  struct byte_buffer b = BUFFER_INIT();
0882252017-01-07Arne Goedeke  buffer_set_flags(&b, BUFFER_GROW_EXACT);
c9ec4d2017-01-01Arne Goedeke  /* for small reads we allocate the whole size in the beginning, * instead of only by individual chunks. We may want to change * what small means. */
0882252017-01-07Arne Goedeke  if (r < 65*1024) buffer_ensure_space(&b, r+1);
f126b62010-11-19Henrik Grubbström (Grubba) 
7563742016-11-08Arne Goedeke  SET_ONERROR(ebuf, buffer_free, &b);
f126b62010-11-19Henrik Grubbström (Grubba)  do{ int e;
c9ec4d2017-01-01Arne Goedeke  const INT32 CHUNK = 1024 * 8; INT32 try_read=MINIMUM(CHUNK,r); /* allocate try_read bytes + the trailing null byte */
0882252017-01-07Arne Goedeke  buffer_ensure_space(&b, try_read+1);
f126b62010-11-19Henrik Grubbström (Grubba)  #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL message.msg.msg_control = &message.cmsgbuf; message.msg.msg_controllen = sizeof(message.cmsgbuf); #else
7589632011-01-26Henrik Grubbström (Grubba)  message.msg.msg_accrights = (void *)&message.cmsgbuf;
f126b62010-11-19Henrik Grubbström (Grubba)  message.msg.msg_accrightslen = sizeof(message.cmsgbuf); #endif
2d10fb2016-12-29Arne Goedeke  message.iov.iov_base = buffer_alloc(&b, try_read);
f126b62010-11-19Henrik Grubbström (Grubba)  message.iov.iov_len = try_read; THREADS_ALLOW(); i = recvmsg(fd, &message.msg, 0); e=errno; THREADS_DISALLOW(); check_threads_etc(); if(i>0) { bytes_read+=i; r-=i; if ( #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL message.msg.msg_controllen #else message.msg.msg_accrightslen #endif ) { check_message(&message.msg); } if (i != try_read) {
2d10fb2016-12-29Arne Goedeke  buffer_remove(&b, try_read - i);
f126b62010-11-19Henrik Grubbström (Grubba)  } if(!all) break; } else if(i==0) {
2d10fb2016-12-29Arne Goedeke  buffer_remove(&b, try_read);
f126b62010-11-19Henrik Grubbström (Grubba)  break; } else {
2d10fb2016-12-29Arne Goedeke  buffer_remove(&b, try_read);
f126b62010-11-19Henrik Grubbström (Grubba)  if(e != EINTR) { ERRNO=e; if(!bytes_read) {
7563742016-11-08Arne Goedeke  buffer_free(&b);
f126b62010-11-19Henrik Grubbström (Grubba)  UNSET_ONERROR(ebuf); return 0; } break; } } }while(r); UNSET_ONERROR(ebuf); if(!SAFE_IS_ZERO(& THIS->event_cbs[PIKE_FD_READ])) ADD_FD_EVENTS (THIS, PIKE_BIT_FD_READ);
2d10fb2016-12-29Arne Goedeke  return buffer_finish_pike_string(&b);
f126b62010-11-19Henrik Grubbström (Grubba)  } } /* Send a set of iovecs and fds over an fd. */ static int writev_fds(int fd, struct iovec *iov, int iovcnt, int *fds, int num_fds) { int retval, e; struct msghdr msg; #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7589632011-01-26Henrik Grubbström (Grubba)  /* XPG 4.2 */
f126b62010-11-19Henrik Grubbström (Grubba) 
b59dd02011-09-24Henrik Grubbström (Grubba) #ifndef CMSG_SPACE
2fe8882011-09-20Henrik Grubbström (Grubba) #define CMSG_SPACE(X) CMSG_LEN(X) #endif struct cmsghdr *cmsg = malloc(CMSG_SPACE(num_fds * sizeof(int))); #if 0 fprintf(stderr, "writev_fds(%d, %p, %d, %p, %d)\n", fd, iov, iovcnt, fds, num_fds); for (e = 0; e < num_fds; e++) { fprintf(stderr, " fd #%d: %d\n", e, fds[e]); } #endif /* 0 */
f126b62010-11-19Henrik Grubbström (Grubba)  if (!cmsg) { errno = ENOMEM; return -1; }
2fe8882011-09-20Henrik Grubbström (Grubba) 
f126b62010-11-19Henrik Grubbström (Grubba)  msg.msg_control = cmsg; msg.msg_controllen = cmsg->cmsg_len = CMSG_LEN(num_fds * sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS;
2fe8882011-09-20Henrik Grubbström (Grubba) 
59fc9e2014-09-03Martin Nilsson  memcpy(CMSG_DATA(cmsg), fds, num_fds * sizeof(int));
7589632011-01-26Henrik Grubbström (Grubba)  msg.msg_flags = 0;
2fe8882011-09-20Henrik Grubbström (Grubba) 
f126b62010-11-19Henrik Grubbström (Grubba) #else
7589632011-01-26Henrik Grubbström (Grubba)  /* BSD */ msg.msg_accrights = (void *)fds;
f126b62010-11-19Henrik Grubbström (Grubba)  msg.msg_accrightslen = num_fds * sizeof(int); #endif msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = iovcnt; retval = sendmsg(fd, &msg, 0); #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL e = errno; free(cmsg); errno = e; #endif return retval; } #endif /* HAVE_PIKE_SEND_FD */
74dfe82012-12-30Jonas Walldén static struct pike_string *do_read_oob(int UNUSED(fd),
c201101998-03-25Henrik Grubbström (Grubba)  INT32 r, int all,
64129c2014-09-28Henrik Grubbström (Grubba)  INT_TYPE *err)
c201101998-03-25Henrik Grubbström (Grubba) { ONERROR ebuf; INT32 bytes_read,i;
9040562003-10-19Martin Stjernholm  struct pike_string *str;
c201101998-03-25Henrik Grubbström (Grubba)  bytes_read=0; *err=0; str=begin_shared_string(r);
fb22942008-06-16Martin Stjernholm  SET_ONERROR(ebuf, do_free_unlinked_pike_string, str);
c201101998-03-25Henrik Grubbström (Grubba)  do{
65c1621999-06-10Fredrik Hübinette (Hubbe)  int e;
c201101998-03-25Henrik Grubbström (Grubba)  int fd=FD; THREADS_ALLOW(); i=fd_recv(fd, str->str+bytes_read, r, MSG_OOB);
ae39322003-09-30Martin Stjernholm  e=errno;
c201101998-03-25Henrik Grubbström (Grubba)  THREADS_DISALLOW();
700dac2002-02-05Martin Stjernholm  check_threads_etc();
c201101998-03-25Henrik Grubbström (Grubba)  if(i>0) { r-=i; bytes_read+=i; if(!all) break; }
3fce482010-02-20Stephen R. van den Berg  else if ((i==0) || (e == EINVAL) #ifdef ECONNRESET || (e == ECONNRESET) #endif
edb5102010-02-19Stephen R. van den Berg #ifdef EOPNOTSUPP || (e == EOPNOTSUPP) #endif )
c201101998-03-25Henrik Grubbström (Grubba)  {
566f752009-02-06Henrik Grubbström (Grubba)  /* No out of band data available. */
c201101998-03-25Henrik Grubbström (Grubba)  break; }
65c1621999-06-10Fredrik Hübinette (Hubbe)  else if(e != EINTR)
c201101998-03-25Henrik Grubbström (Grubba)  {
65c1621999-06-10Fredrik Hübinette (Hubbe)  *err=e;
c201101998-03-25Henrik Grubbström (Grubba)  if(!bytes_read) {
fb22942008-06-16Martin Stjernholm  do_free_unlinked_pike_string(str);
c201101998-03-25Henrik Grubbström (Grubba)  UNSET_ONERROR(ebuf); return 0; } break; } }while(r); UNSET_ONERROR(ebuf);
ee71702000-01-30Per Hedbor 
10dac82004-04-05Martin Stjernholm  if(!SAFE_IS_ZERO(& THIS->event_cbs[PIKE_FD_READ_OOB])) ADD_FD_EVENTS (THIS, PIKE_BIT_FD_READ_OOB);
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
c201101998-03-25Henrik Grubbström (Grubba)  if(bytes_read == str->len) { return end_shared_string(str); }else{
d5b1e22000-11-29Fredrik Hübinette (Hubbe)  return end_and_resize_shared_string(str, bytes_read);
c201101998-03-25Henrik Grubbström (Grubba)  } }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl string read() *! @decl string read(int len) *! @decl string read(int len, int(0..1) not_all) *!
f53cc02003-10-15Martin Stjernholm  *! Read data from a file or a stream.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! Attempts to read @[len] bytes from the file, and return it as a
a3ead52003-10-24Martin Stjernholm  *! string. Less than @[len] bytes can be returned if:
f53cc02003-10-15Martin Stjernholm  *! *! @ul *! @item *! end-of-file is encountered for a normal file, or *! @item
a3ead52003-10-24Martin Stjernholm  *! it's a stream that has been closed from the other end, or
f53cc02003-10-15Martin Stjernholm  *! @item
a3ead52003-10-24Martin Stjernholm  *! it's a stream in nonblocking mode, or *! @item *! it's a stream and @[not_all] is set, or
978dbc2003-10-15Martin Stjernholm  *! @item *! @[not_all] isn't set and an error occurred (see below).
f53cc02003-10-15Martin Stjernholm  *! @endul
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
5601732004-11-30Martin Stjernholm  *! If @[not_all] is nonzero, @[read()] does not try its best to read *! as many bytes as you have asked for, but merely returns as much as
31b7752005-01-27Martin Stjernholm  *! the system read function returns. This is mainly useful with *! stream devices which can return exactly one row or packet at a *! time. If @[not_all] is used in blocking mode, @[read()] only *! blocks if there's no data at all available.
1b5eb42003-10-15Martin Stjernholm  *!
5601732004-11-30Martin Stjernholm  *! If something goes wrong and @[not_all] is set, zero is returned. *! If something goes wrong and @[not_all] is zero or left out, then *! either zero or a string shorter than @[len] is returned. If the *! problem persists then a later call to @[read()] fails and returns *! zero, however.
1b5eb42003-10-15Martin Stjernholm  *! *! If everything went fine, a call to @[errno()] directly afterwards
5601732004-11-30Martin Stjernholm  *! returns zero. That includes an end due to end-of-file or remote *! close.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
5601732004-11-30Martin Stjernholm  *! If no arguments are given, @[read()] reads to the end of the file *! or stream.
f53cc02003-10-15Martin Stjernholm  *!
9ea5be2011-09-07Henrik Grubbström (Grubba)  *! If any file descriptors have been sent by the other side of the *! stream, @[receive_fd()] will be called once for every sent file *! descriptor. *!
f53cc02003-10-15Martin Stjernholm  *! @note *! It's not necessary to set @[not_all] to avoid blocking reading *! when nonblocking mode is used. *! *! @note *! When at the end of a file or stream, repeated calls to @[read()]
9ea5be2011-09-07Henrik Grubbström (Grubba)  *! will return the empty string since it's not considered an error. *! The empty string is never returned in other cases, unless nonblocking
5601732004-11-30Martin Stjernholm  *! mode is used or @[len] is zero.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @seealso
9ea5be2011-09-07Henrik Grubbström (Grubba)  *! @[read_oob()], @[write()], @[receive_fd()], @[send_fd()]
9c052f2001-02-15Henrik Grubbström (Grubba)  */
2b10c61996-12-03Fredrik Hübinette (Hubbe) static void file_read(INT32 args) { struct pike_string *tmp; INT32 all, len; if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
2b10c61996-12-03Fredrik Hübinette (Hubbe)  if(!args) { len=0x7fffffff; } else {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("read", 1, "int");
5923b12000-07-06Fredrik Hübinette (Hubbe)  len=Pike_sp[-args].u.integer;
75692c1998-03-21Fredrik Hübinette (Hubbe)  if(len<0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot read negative number of characters.\n");
dcae492014-09-27Henrik Grubbström (Grubba)  if (!len && SUBTYPEOF(Pike_sp[-args])) { len = 0x7fffffff; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
2b10c61996-12-03Fredrik Hübinette (Hubbe) 
9f516a2001-12-16Martin Stjernholm  if(args > 1 && !UNSAFE_IS_ZERO(Pike_sp+1-args))
2b10c61996-12-03Fredrik Hübinette (Hubbe)  { all=0; }else{ all=1; } pop_n_elems(args);
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD /* Check if there's any need to use recvmsg(2). */ if ((THIS->open_mode & fd_SEND_FD) && (THIS->flags & FILE_HAVE_RECV_FD)) { if ((tmp = do_recvmsg(len, all))) push_string(tmp); else { errno = ERRNO; push_int(0); } } else #endif /* HAVE_PIKE_SEND_FD */ if((tmp=do_read(FD, len, all, & ERRNO))) push_string(tmp); else { errno = ERRNO; push_int(0); }
31b7752005-01-27Martin Stjernholm 
f010202011-11-16Tobias S. Josefowitz  if (!(THIS->open_mode & FILE_NONBLOCKING)) INVALIDATE_CURRENT_TIME();
31b7752005-01-27Martin Stjernholm  /* Race: A backend in another thread might have managed to set these * again for something that arrived after the read above. Not that * bad - it will get through in a later backend round. */ THIS->box.revents &= ~(PIKE_BIT_FD_READ|PIKE_BIT_FD_READ_OOB);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1d65931998-07-08Fredrik Hübinette (Hubbe) #ifdef HAVE_AND_USE_POLL
7d84b61998-09-20Henrik Grubbström (Grubba) #ifdef HAVE_POLL_H
1d65931998-07-08Fredrik Hübinette (Hubbe) #include <poll.h>
7d84b61998-09-20Henrik Grubbström (Grubba) #else /* !HAVE_POLL_H */ #ifdef HAVE_SYS_POLL_H #include <sys/poll.h> #else /* !HAVE_SYS_POLL_H */ #undef HAVE_AND_USE_POLL #endif /* HAVE_SYS_POLL_H */ #endif /* HAVE_POLL_H */ #else /* HAVE_AND_USE_POLL */
1d65931998-07-08Fredrik Hübinette (Hubbe) 
943e0a1998-07-08Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #endif
1d65931998-07-08Fredrik Hübinette (Hubbe) #endif
943e0a1998-07-08Fredrik Hübinette (Hubbe) 
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int(-1..1) peek()
ea41202001-03-10Mirar (Pontus Hagland)  *! @decl int(-1..1) peek(int|float timeout)
53edbf2007-07-26Henrik Grubbström (Grubba)  *! @decl int(-1..1) peek(int|float timeout, int not_eof)
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
ea41202001-03-10Mirar (Pontus Hagland)  *! Check if there is data available to read, *! or wait some time for available data to read.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
e784c82006-05-31Henrik Grubbström (Grubba)  *! More specifically, a later call to @[read()] will return *! immediately, either due to data being present, or due to *! some error (eg if a socket has been closed). *!
53edbf2007-07-26Henrik Grubbström (Grubba)  *! @param timeout *! Timeout in seconds. *! *! @param not_eof *! Flag for specifying handling of end of file. *! The following values are currently defined: *! @int *! @value 0 *! Traditional (and default) behaviour. Return @expr{1@} *! at EOF. *! *! @value 1
18a5112008-03-14Henrik Grubbström (Grubba)  *! Regard EOF as an error. Return @expr{-1@} and set @[errno()] *! to return @expr{EPIPE@} at EOF.
53edbf2007-07-26Henrik Grubbström (Grubba)  *! @endint *! *! @returns *! @int *! @value 1 *! There is data available to @[read()], or @[not_eof] is *! @expr{0@} (zero) and we're at EOF. A later call to *! @[read()] will not block. *! *! @value 0 *! There is no data available (ie timeout). *! *! @value -1 *! Error condition. The error code returned by @[errno()] *! has been updated. *! @endint
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @seealso *! @[errno()], @[read()]
2069362001-03-10Mirar (Pontus Hagland)  *! *! @note *! The function may be interrupted prematurely
13670c2015-05-25Martin Nilsson  *! of the timeout (due to signals);
2069362001-03-10Mirar (Pontus Hagland)  *! check the timing manually if this is imporant.
9c052f2001-02-15Henrik Grubbström (Grubba)  */
943e0a1998-07-08Fredrik Hübinette (Hubbe) static void file_peek(INT32 args) {
1d65931998-07-08Fredrik Hübinette (Hubbe)  int ret;
53edbf2007-07-26Henrik Grubbström (Grubba)  int not_eof = 0; FLOAT_TYPE tf = 0.0;
1d65931998-07-08Fredrik Hübinette (Hubbe) 
53edbf2007-07-26Henrik Grubbström (Grubba)  get_all_args("peek",args,".%F%d",&tf,&not_eof);
1d65931998-07-08Fredrik Hübinette (Hubbe) 
ea41202001-03-10Mirar (Pontus Hagland)  {
53edbf2007-07-26Henrik Grubbström (Grubba) #ifdef HAVE_AND_USE_POLL struct pollfd fds;
22fbe82010-02-16Henrik Grubbström (Grubba)  int timeout = 0;
93c5b22008-07-28Henrik Grubbström (Grubba)  if (args && !IS_UNDEFINED(Pike_sp - args)) { timeout = (int)(tf*1000); /* ignore overflow for now */ }
53edbf2007-07-26Henrik Grubbström (Grubba)  fds.fd=FD; fds.events=POLLIN; fds.revents=0;
1d65931998-07-08Fredrik Hübinette (Hubbe) 
85628c2010-02-15Stephen R. van den Berg  if (timeout) { THREADS_ALLOW(); ret=poll(&fds, 1, timeout); THREADS_DISALLOW(); } else {
2e17ca2010-02-16Stephen R. van den Berg  ret=poll(&fds, 1, 0);
85628c2010-02-15Stephen R. van den Berg  }
53edbf2007-07-26Henrik Grubbström (Grubba)  if(ret < 0) { ERRNO=errno; ret=-1;
08af5f2007-07-29Henrik Grubbström (Grubba)  } else if (fds.revents & POLLERR) {
53edbf2007-07-26Henrik Grubbström (Grubba)  int err = EPIPE; /* Value in case of non-socket. */ ACCEPT_SIZE_T len = sizeof(err); ret = -1;
d26bc32007-07-29Henrik Grubbström (Grubba)  getsockopt(FD, SOL_SOCKET, SO_ERROR, (void *)&err, &len);
53edbf2007-07-26Henrik Grubbström (Grubba)  ERRNO = err;
08af5f2007-07-29Henrik Grubbström (Grubba)  } else if (fds.revents & POLLNVAL) {
53edbf2007-07-26Henrik Grubbström (Grubba)  ret = -1; errno = EINVAL;
08af5f2007-07-29Henrik Grubbström (Grubba)  } else if (not_eof && (fds.revents & POLLHUP)) {
53edbf2007-07-26Henrik Grubbström (Grubba)  ret = -1; ERRNO = EPIPE; }else{ ret = (ret > 0) && (fds.revents & POLLIN); }
1d65931998-07-08Fredrik Hübinette (Hubbe) #else
53edbf2007-07-26Henrik Grubbström (Grubba)  fd_set tmp; struct timeval tv;
1d65931998-07-08Fredrik Hübinette (Hubbe) 
939e9c2010-02-23Stephen R. van den Berg  tv.tv_usec=0;
53edbf2007-07-26Henrik Grubbström (Grubba)  tv.tv_sec=0; fd_FD_ZERO(&tmp); fd_FD_SET(FD, &tmp); ret = FD;
1d65931998-07-08Fredrik Hübinette (Hubbe) 
93c5b22008-07-28Henrik Grubbström (Grubba)  if (args && !IS_UNDEFINED(Pike_sp - args)) { tv.tv_sec=(int)tf; tv.tv_usec=(int)(1000000*(tf-tv.tv_sec)); }
ea41202001-03-10Mirar (Pontus Hagland) 
53edbf2007-07-26Henrik Grubbström (Grubba)  /* FIXME: Handling of EOF and not_eof */
943e0a1998-07-08Fredrik Hübinette (Hubbe) 
939e9c2010-02-23Stephen R. van den Berg  if(tv.tv_sec || tv.tv_usec) { THREADS_ALLOW(); ret = fd_select(ret+1,&tmp,0,0,&tv); THREADS_DISALLOW(); } else ret = fd_select(ret+1,&tmp,0,0,&tv);
53edbf2007-07-26Henrik Grubbström (Grubba)  if(ret < 0) { ERRNO=errno; ret=-1; }else{ ret = (ret > 0) && fd_FD_ISSET(FD, &tmp); }
1d65931998-07-08Fredrik Hübinette (Hubbe) #endif
53edbf2007-07-26Henrik Grubbström (Grubba)  }
1d65931998-07-08Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(ret);
943e0a1998-07-08Fredrik Hübinette (Hubbe) }
ea41202001-03-10Mirar (Pontus Hagland) 
2581562004-04-14Henrik Grubbström (Grubba) /* NOTE: Some versions of AIX seem to have a * #define events reqevents * in one of the poll headerfiles. This will break * the fd_box event handling. */ #undef events
943e0a1998-07-08Fredrik Hübinette (Hubbe) 
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl string read_oob() *! @decl string read_oob(int len) *! @decl string read_oob(int len, int(0..1) not_all) *! *! Attempts to read @[len] bytes of out-of-band data from the stream,
a3ead52003-10-24Martin Stjernholm  *! and returns it as a string. Less than @[len] bytes can be returned *! if:
978dbc2003-10-15Martin Stjernholm  *! *! @ul *! @item *! the stream has been closed from the other end, or *! @item *! nonblocking mode is used, or *! @item
a3ead52003-10-24Martin Stjernholm  *! @[not_all] is set, or *! @item
978dbc2003-10-15Martin Stjernholm  *! @[not_all] isn't set and an error occurred (see below). *! @endul *!
5601732004-11-30Martin Stjernholm  *! If @[not_all] is nonzero, @[read_oob()] only returns as many bytes *! of out-of-band data as are currently available.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
5601732004-11-30Martin Stjernholm  *! If something goes wrong and @[not_all] is set, zero is returned. *! If something goes wrong and @[not_all] is zero or left out, then *! either zero or a string shorter than @[len] is returned. If the *! problem persists then a later call to @[read_oob()] fails and *! returns zero, however.
978dbc2003-10-15Martin Stjernholm  *! *! If everything went fine, a call to @[errno()] directly afterwards
5601732004-11-30Martin Stjernholm  *! returns zero. That includes an end due to remote close.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
5601732004-11-30Martin Stjernholm  *! If no arguments are given, @[read_oob()] reads to the end of the *! stream.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @note
5601732004-11-30Martin Stjernholm  *! It is not guaranteed that all out-of-band data sent from the *! other end is received. Most streams only allow for a single byte *! of out-of-band data at a time.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
978dbc2003-10-15Martin Stjernholm  *! @note *! It's not necessary to set @[not_all] to avoid blocking reading *! when nonblocking mode is used. *! *! @note *! When at the end of a file or stream, repeated calls to @[read()]
5601732004-11-30Martin Stjernholm  *! returns the empty string since it's not considered an error. The *! empty string is never returned in other cases, unless nonblocking *! mode is used or @[len] is zero.
978dbc2003-10-15Martin Stjernholm  *!
9c052f2001-02-15Henrik Grubbström (Grubba)  *! @seealso *! @[read()], @[write_oob()] */
c201101998-03-25Henrik Grubbström (Grubba) static void file_read_oob(INT32 args) { struct pike_string *tmp; INT32 all, len; if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
c201101998-03-25Henrik Grubbström (Grubba)  if(!args) { len=0x7fffffff; } else {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("read_oob", 1, "int");
5923b12000-07-06Fredrik Hübinette (Hubbe)  len=Pike_sp[-args].u.integer;
c201101998-03-25Henrik Grubbström (Grubba)  if(len<0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot read negative number of characters.\n");
c201101998-03-25Henrik Grubbström (Grubba)  }
9f516a2001-12-16Martin Stjernholm  if(args > 1 && !UNSAFE_IS_ZERO(Pike_sp+1-args))
c201101998-03-25Henrik Grubbström (Grubba)  { all=0; }else{ all=1; } pop_n_elems(args); if((tmp=do_read_oob(FD, len, all, & ERRNO))) push_string(tmp);
ae39322003-09-30Martin Stjernholm  else { errno = ERRNO;
c201101998-03-25Henrik Grubbström (Grubba)  push_int(0);
ae39322003-09-30Martin Stjernholm  }
31b7752005-01-27Martin Stjernholm 
f010202011-11-16Tobias S. Josefowitz  if (!(THIS->open_mode & FILE_NONBLOCKING)) INVALIDATE_CURRENT_TIME();
31b7752005-01-27Martin Stjernholm  /* Race: A backend in another thread might have managed to set these * again for something that arrived after the read above. Not that * bad - it will get through in a later backend round. */ THIS->box.revents &= ~(PIKE_BIT_FD_READ|PIKE_BIT_FD_READ_OOB);
c201101998-03-25Henrik Grubbström (Grubba) }
ca6bd02012-05-01Bill Welliver static short get_fd_event_flags(struct my_file *f) { if(f->box.backend) { return f->box.flags; } else return 0; } static void set_fd_event_cb (struct my_file *f, struct svalue *cb, int event, int flags)
10dac82004-04-05Martin Stjernholm { if (UNSAFE_IS_ZERO (cb)) { free_svalue (&f->event_cbs[event]);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(f->event_cbs[event], PIKE_T_INT, NUMBER_NUMBER, integer, 0);
ca6bd02012-05-01Bill Welliver  SUB_FD_EVENTS2 (f, 1 << event, flags);
10dac82004-04-05Martin Stjernholm  } else {
d156802008-01-01Henrik Grubbström (Grubba) #ifdef __NT__
d1abc62008-01-01Henrik Grubbström (Grubba)  if (!(fd_query_properties(f->box.fd, fd_CAN_NONBLOCK) & fd_CAN_NONBLOCK)) {
d156802008-01-01Henrik Grubbström (Grubba)  Pike_error("Setting backend callback on a non-socket!\n"); } #endif /* __NT__ */
10dac82004-04-05Martin Stjernholm  assign_svalue (&f->event_cbs[event], cb);
ca6bd02012-05-01Bill Welliver  ADD_FD_EVENTS2 (f, 1 << event, flags);
10dac82004-04-05Martin Stjernholm  }
a1ef721998-04-05Fredrik Hübinette (Hubbe) }
10dac82004-04-05Martin Stjernholm #undef CBFUNCS
2e005f2014-02-25Per Hedbor 
10dac82004-04-05Martin Stjernholm #define CBFUNCS(CB, EVENT) \ static void PIKE_CONCAT(file_set_,CB) (INT32 args) \ { \ if(!args) \
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("set_" #CB, 1); \
ca6bd02012-05-01Bill Welliver  set_fd_event_cb (THIS, Pike_sp-args, EVENT, 0); \
10dac82004-04-05Martin Stjernholm  }
ca6bd02012-05-01Bill Welliver #define CBFUNCS2(CB, EVENT) \ static void PIKE_CONCAT(file_set_,CB) (INT32 args) \
6e13d12012-05-13Henrik Grubbström (Grubba)  { \
2ab6542012-05-13Henrik Grubbström (Grubba)  if(args<2) \
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("set_" #CB, 2); \
16a24b2012-05-14Martin Nilsson  if (TYPEOF(Pike_sp[1-args]) != PIKE_T_INT) \
de22f72014-08-25Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("set_" #CB, 2, "int"); \
2ab6542012-05-13Henrik Grubbström (Grubba)  set_fd_event_cb (THIS, Pike_sp-args, EVENT, \ Pike_sp[1-args].u.integer); \
6e13d12012-05-13Henrik Grubbström (Grubba)  }
ca6bd02012-05-01Bill Welliver 
10dac82004-04-05Martin Stjernholm CBFUNCS(read_callback, PIKE_FD_READ) CBFUNCS(write_callback, PIKE_FD_WRITE) CBFUNCS(read_oob_callback, PIKE_FD_READ_OOB) CBFUNCS(write_oob_callback, PIKE_FD_WRITE_OOB)
ca6bd02012-05-01Bill Welliver CBFUNCS2(fs_event_callback, PIKE_FD_FS_EVENT)
65820a2012-05-02Bill Welliver 
ca6bd02012-05-01Bill Welliver static void file_query_fs_event_flags(INT32 args) { short flags; pop_n_elems(args);
13670c2015-05-25Martin Nilsson 
ca6bd02012-05-01Bill Welliver  flags = get_fd_event_flags(THIS); push_int(flags); }
c201101998-03-25Henrik Grubbström (Grubba) 
96f63c2015-11-25Henrik Grubbström (Grubba) static void file__enable_callbacks(INT32 UNUSED(args))
a34e701998-07-26Fredrik Hübinette (Hubbe) {
10dac82004-04-05Martin Stjernholm  struct my_file *f = THIS; size_t ev; int cb_events = 0;
7864202006-01-14Martin Stjernholm #if 0
57ad1e1998-12-06Fredrik Hübinette (Hubbe)  if(FD<0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File is not open.\n");
7864202006-01-14Martin Stjernholm #endif
57ad1e1998-12-06Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  debug_check_internals (f); for (ev = 0; ev < NELEM (f->event_cbs); ev++) if (!UNSAFE_IS_ZERO (&f->event_cbs[ev])) cb_events |= 1 << ev;
a34e701998-07-26Fredrik Hübinette (Hubbe) 
b2d98d2009-03-19Henrik Grubbström (Grubba)  if (cb_events) { if (FD >= 0 && !(fd_query_properties(FD, fd_CAN_NONBLOCK) & fd_CAN_NONBLOCK)) Pike_error("Callback operations not supported for this file.\n"); ADD_FD_EVENTS (f, cb_events); }
a34e701998-07-26Fredrik Hübinette (Hubbe) }
96f63c2015-11-25Henrik Grubbström (Grubba) static void file__disable_callbacks(INT32 UNUSED(args))
a34e701998-07-26Fredrik Hübinette (Hubbe) {
10dac82004-04-05Martin Stjernholm  struct my_file *f = THIS;
7864202006-01-14Martin Stjernholm #if 0
57ad1e1998-12-06Fredrik Hübinette (Hubbe)  if(FD<0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File is not open.\n");
7864202006-01-14Martin Stjernholm #endif
a34e701998-07-26Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  SUB_FD_EVENTS (f, ~0);
a34e701998-07-26Fredrik Hübinette (Hubbe) }
c201101998-03-25Henrik Grubbström (Grubba) 
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int write(string data) *! @decl int write(string format, mixed ... extras) *! @decl int write(array(string) data) *! @decl int write(array(string) format, mixed ... extras) *! *! Write data to a file or a stream. *!
e0baea2014-07-12Henrik Grubbström (Grubba)  *! If there are any file descriptors that have been queued for sending *! (with @[send_fd()]), they will be sent.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
e0baea2014-07-12Henrik Grubbström (Grubba)  *! @param data *! Data to write.
63dba12003-10-28Martin Stjernholm  *!
e0baea2014-07-12Henrik Grubbström (Grubba)  *! If @[data] is an array of strings, they are written in sequence.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
e0baea2014-07-12Henrik Grubbström (Grubba)  *! @param format *! @param extras *! If more than one argument is given, @[sprintf()] is used to format *! them using @[format]. If @[format] is an array, the strings in it *! are concatenated and the result is used as format string.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
e0baea2014-07-12Henrik Grubbström (Grubba)  *! @returns *! Writes @[data] and returns the number of bytes that were *! actually written.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
e0baea2014-07-12Henrik Grubbström (Grubba)  *! @int *! @value 1.. *! The number of bytes successfully written to the OS buffers.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
e0baea2014-07-12Henrik Grubbström (Grubba)  *! This can be less than the size of the given data if eg: *! @ul *! @item *! Some data was written successfully and then something went *! wrong. *! *! If only some data was written due to an error and that error *! persists, then a later call to @[write()] will fail and return *! @expr{-1@}. *! *! @item *! Nonblocking mode is used and not all data could be written *! without blocking. *! @endul *! *! @value 0 *! No bytes were written. This may be due to *! @ul *! @item *! @[data] or the formatted data being the empty string. *! *! @item *! Nonblocking mode is used and no data could be written *! without blocking. *! @endul *! *! @value -1 *! Something went wrong and no bytes were written. *! @endint *! *! If everything went fine, a call to @[errno()] directly afterwards *! returns zero.
f126b62010-11-19Henrik Grubbström (Grubba)  *!
9c052f2001-02-15Henrik Grubbström (Grubba)  *! @note
f53cc02003-10-15Martin Stjernholm  *! Writing of wide strings is not supported. You have to encode the *! data somehow, e.g. with @[string_to_utf8] or with one of the
0b8d2f2013-06-17Martin Nilsson  *! charsets supported by @[Charset.encoder].
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @seealso
f126b62010-11-19Henrik Grubbström (Grubba)  *! @[read()], @[write_oob()], @[send_fd()]
9c052f2001-02-15Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_write(INT32 args) {
d098b22000-08-09Henrik Grubbström (Grubba)  ptrdiff_t written, i;
07513e1996-10-04Fredrik Hübinette (Hubbe)  struct pike_string *str;
c0de561996-02-18Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(args<1 || ((TYPEOF(Pike_sp[-args]) != PIKE_T_STRING) && (TYPEOF(Pike_sp[-args]) != PIKE_T_ARRAY)))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("write", 1, "string|array(string)");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
4451331999-04-01Henrik Grubbström (Grubba)  if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open for write.\n");
ee71702000-01-30Per Hedbor 
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-args]) == PIKE_T_ARRAY) {
5923b12000-07-06Fredrik Hübinette (Hubbe)  struct array *a = Pike_sp[-args].u.array;
637f382004-05-14Martin Nilsson 
2575242004-05-14Martin Nilsson  if( (a->type_field & ~BIT_STRING) && (array_fix_type_field(a) & ~BIT_STRING) )
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("write", 1, "string|array(string)");
637f382004-05-14Martin Nilsson 
4451331999-04-01Henrik Grubbström (Grubba)  i = a->size;
637f382004-05-14Martin Nilsson  while(i--) if (a->item[i].u.string->size_shift)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad argument 1 to file->write().\n"
637f382004-05-14Martin Nilsson  "Element %ld is a wide string.\n",
cc7cf42015-10-14Martin Nilsson  (long)i);
4451331999-04-01Henrik Grubbström (Grubba)  #ifdef HAVE_WRITEV if (args > 1) { #endif /* HAVE_WRITEV */ ref_push_array(a);
7863d62005-05-06Martin Nilsson  push_empty_string();
30d4f81999-04-01Henrik Grubbström (Grubba)  o_multiply();
5923b12000-07-06Fredrik Hübinette (Hubbe)  Pike_sp--; dmalloc_touch_svalue(Pike_sp);
61acc72001-09-06Martin Stjernholm  Pike_sp[-args] = *Pike_sp;
fcfe412001-09-06Fredrik Hübinette (Hubbe)  free_array(a);
4451331999-04-01Henrik Grubbström (Grubba)  #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING) {
6de0852004-01-23Martin Nilsson  Pike_error("Bad return value from string multiplication.\n");
4451331999-04-01Henrik Grubbström (Grubba)  } #endif /* PIKE_DEBUG */ #ifdef HAVE_WRITEV } else if (!a->size) { /* Special case for empty array */
63dba12003-10-28Martin Stjernholm  ERRNO = 0;
4451331999-04-01Henrik Grubbström (Grubba)  pop_stack(); push_int(0); return; } else {
dc8d022014-04-27Martin Nilsson  struct iovec *iovbase = xalloc(sizeof(struct iovec)*a->size);
4451331999-04-01Henrik Grubbström (Grubba)  struct iovec *iov = iovbase; int iovcnt = a->size;
f010202011-11-16Tobias S. Josefowitz  if (!(THIS->open_mode & FILE_NONBLOCKING)) INVALIDATE_CURRENT_TIME();
4451331999-04-01Henrik Grubbström (Grubba)  i = a->size; while(i--) {
2402451999-04-01Henrik Grubbström (Grubba)  if (a->item[i].u.string->len) { iov[i].iov_base = a->item[i].u.string->str; iov[i].iov_len = a->item[i].u.string->len; } else { iov++; iovcnt--; }
4451331999-04-01Henrik Grubbström (Grubba)  } for(written = 0; iovcnt; check_signals(0,0,0)) { int fd = FD;
700dac2002-02-05Martin Stjernholm  int e;
4451331999-04-01Henrik Grubbström (Grubba)  int cnt = iovcnt;
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD int *fd_info = NULL; int num_fds = 0; if (THIS->fd_info && (num_fds = THIS->fd_info[1])) { fd_info = THIS->fd_info; THIS->fd_info = NULL; } #endif
4451331999-04-01Henrik Grubbström (Grubba)  THREADS_ALLOW();
b5bb2c1999-04-01Fredrik Hübinette (Hubbe)  #ifdef IOV_MAX if (cnt > IOV_MAX) cnt = IOV_MAX; #endif #ifdef MAX_IOVEC if (cnt > MAX_IOVEC) cnt = MAX_IOVEC; #endif
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (fd_info) { i = writev_fds(fd, iov, cnt, fd_info + 2, num_fds); } else #endif i = writev(fd, iov, cnt);
4451331999-04-01Henrik Grubbström (Grubba)  THREADS_DISALLOW();
2402451999-04-01Henrik Grubbström (Grubba)  /* fprintf(stderr, "writev(%d, 0x%08x, %d) => %d\n", fd, (unsigned int)iov, cnt, i); */
700dac2002-02-05Martin Stjernholm  e=errno; /* check_threads_etc may effect errno */ check_threads_etc();
4451331999-04-01Henrik Grubbström (Grubba)  if(i<0) {
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (fd_info) { restore_fd_info(fd_info); } #endif
700dac2002-02-05Martin Stjernholm  switch(e)
4451331999-04-01Henrik Grubbström (Grubba)  { default: free(iovbase);
ae39322003-09-30Martin Stjernholm  ERRNO=errno=e;
4451331999-04-01Henrik Grubbström (Grubba)  pop_n_elems(args); if (!written) { push_int(-1); } else { push_int(written); }
e011922014-10-19Henrik Grubbström (Grubba)  /* Minor race - see below. */ THIS->box.revents &= ~(PIKE_BIT_FD_WRITE|PIKE_BIT_FD_WRITE_OOB);
4451331999-04-01Henrik Grubbström (Grubba)  return; case EINTR: continue; case EWOULDBLOCK: break;
f126b62010-11-19Henrik Grubbström (Grubba)  /* FIXME: Special case for ENOTSOCK? */
4451331999-04-01Henrik Grubbström (Grubba)  } break; }else{ written += i;
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (fd_info) { THIS->fd_info = fd_info; if (i) { do_close_fd_info(THIS->fd_info = fd_info); } } #endif
4451331999-04-01Henrik Grubbström (Grubba)  /* Avoid extra writev() */ if(THIS->open_mode & FILE_NONBLOCKING) break; while(i) {
9898172000-08-11Henrik Grubbström (Grubba)  if ((ptrdiff_t)iov->iov_len <= i) {
4451331999-04-01Henrik Grubbström (Grubba)  i -= iov->iov_len; iov++; iovcnt--; } else { /* Use cast since iov_base might be a void pointer */ iov->iov_base = ((char *) iov->iov_base) + i; iov->iov_len -= i; i = 0; } } }
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef _REENTRANT if (FD<0) { free(iovbase); Pike_error("File closed while in file->write.\n"); } #endif
4451331999-04-01Henrik Grubbström (Grubba)  } free(iovbase);
e011922014-10-19Henrik Grubbström (Grubba)  /* Minor race - see below. */ THIS->box.revents &= ~(PIKE_BIT_FD_WRITE|PIKE_BIT_FD_WRITE_OOB);
10dac82004-04-05Martin Stjernholm  if(!SAFE_IS_ZERO(& THIS->event_cbs[PIKE_FD_WRITE])) ADD_FD_EVENTS (THIS, PIKE_BIT_FD_WRITE);
4451331999-04-01Henrik Grubbström (Grubba)  ERRNO=0; pop_stack(); push_int(written);
2402451999-04-01Henrik Grubbström (Grubba)  return;
4451331999-04-01Henrik Grubbström (Grubba)  } #endif /* HAVE_WRITEV */ }
017b572011-10-28Henrik Grubbström (Grubba)  /* At this point TYPEOF(Pike_sp[-args]) is PIKE_T_STRING */
4451331999-04-01Henrik Grubbström (Grubba) 
f30ba61998-02-19Fredrik Hübinette (Hubbe)  if(args > 1) { f_sprintf(args); args=1; }
5923b12000-07-06Fredrik Hübinette (Hubbe)  str=Pike_sp[-args].u.string;
7040d02001-01-16Fredrik Hübinette (Hubbe)  if(str->size_shift) Pike_error("Stdio.File->write(): cannot output wide strings.\n");
07513e1996-10-04Fredrik Hübinette (Hubbe) 
49ee321998-10-20Fredrik Hübinette (Hubbe)  for(written=0;written < str->len;check_signals(0,0,0))
c657d01997-01-29Fredrik Hübinette (Hubbe)  {
07513e1996-10-04Fredrik Hübinette (Hubbe)  int fd=FD;
cdf1942000-01-09Fredrik Hübinette (Hubbe)  int e;
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD int *fd_info = NULL; int num_fds = 0; /* fprintf(stderr, "fd_info: %p\n", THIS->fd_info); */ if (THIS->fd_info && (num_fds = THIS->fd_info[1])) { fd_info = THIS->fd_info;
f96c7e2011-09-20Henrik Grubbström (Grubba)  THIS->fd_info = NULL;
f126b62010-11-19Henrik Grubbström (Grubba)  } #endif
07513e1996-10-04Fredrik Hübinette (Hubbe)  THREADS_ALLOW();
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (fd_info) { struct iovec iov; iov.iov_base = str->str + written; iov.iov_len = str->len - written; i = writev_fds(fd, &iov, 1, fd_info + 2, num_fds); } else #endif i=fd_write(fd, str->str + written, str->len - written);
ae39322003-09-30Martin Stjernholm  e=errno;
07513e1996-10-04Fredrik Hübinette (Hubbe)  THREADS_DISALLOW();
c0de561996-02-18Fredrik Hübinette (Hubbe) 
700dac2002-02-05Martin Stjernholm  check_threads_etc();
cdf1942000-01-09Fredrik Hübinette (Hubbe) 
f010202011-11-16Tobias S. Josefowitz  if (!(THIS->open_mode & FILE_NONBLOCKING)) INVALIDATE_CURRENT_TIME();
c0de561996-02-18Fredrik Hübinette (Hubbe)  if(i<0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (fd_info) { restore_fd_info(fd_info); } #endif
cdf1942000-01-09Fredrik Hübinette (Hubbe)  switch(e)
c0de561996-02-18Fredrik Hübinette (Hubbe)  { default:
ae39322003-09-30Martin Stjernholm  ERRNO=errno=e;
c0de561996-02-18Fredrik Hübinette (Hubbe)  pop_n_elems(args);
4451331999-04-01Henrik Grubbström (Grubba)  if (!written) { push_int(-1); } else {
84f8952000-08-16Henrik Grubbström (Grubba)  push_int64(written);
4451331999-04-01Henrik Grubbström (Grubba)  }
31b7752005-01-27Martin Stjernholm  /* Minor race - see below. */ THIS->box.revents &= ~(PIKE_BIT_FD_WRITE|PIKE_BIT_FD_WRITE_OOB);
c0de561996-02-18Fredrik Hübinette (Hubbe)  return;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
c657d01997-01-29Fredrik Hübinette (Hubbe)  case EINTR: continue;
06983f1996-09-22Fredrik Hübinette (Hubbe)  case EWOULDBLOCK: break;
f126b62010-11-19Henrik Grubbström (Grubba)  /* FIXME: Special case for ENOTSOCK? */
c0de561996-02-18Fredrik Hübinette (Hubbe)  }
c657d01997-01-29Fredrik Hübinette (Hubbe)  break; }else{ written+=i;
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (i && fd_info) { do_close_fd_info(THIS->fd_info = fd_info); } #endif
c657d01997-01-29Fredrik Hübinette (Hubbe)  /* Avoid extra write() */ if(THIS->open_mode & FILE_NONBLOCKING) break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef _REENTRANT if(FD<0) Pike_error("File closed while in file->write.\n"); #endif
c657d01997-01-29Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2fe8882011-09-20Henrik Grubbström (Grubba) #ifdef _REENTRANT /* check_signals() may have done something... */ if(FD<0) Pike_error("File closed while in file->write.\n"); #endif
31b7752005-01-27Martin Stjernholm  /* Race: A backend in another thread might have managed to set these * again for buffer space available after the write above. Not that * bad - it will get through in a later backend round. */ THIS->box.revents &= ~(PIKE_BIT_FD_WRITE|PIKE_BIT_FD_WRITE_OOB);
10dac82004-04-05Martin Stjernholm  if(!SAFE_IS_ZERO(& THIS->event_cbs[PIKE_FD_WRITE])) ADD_FD_EVENTS (THIS, PIKE_BIT_FD_WRITE);
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
84f8952000-08-16Henrik Grubbström (Grubba)  push_int64(written);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int write_oob(string data) *! @decl int write_oob(string format, mixed ... extras) *! *! Write out-of-band data to a stream. *!
63dba12003-10-28Martin Stjernholm  *! Writes out-of-band data to a stream and returns how many bytes *! that were actually written. It can be less than the size of the *! given data if some data was written successfully and then *! something went wrong. *! *! -1 is returned if something went wrong and no bytes were written. *! If only some data was written due to an error and that error
5601732004-11-30Martin Stjernholm  *! persists, then a later call to @[write_oob()] fails and returns *! -1.
63dba12003-10-28Martin Stjernholm  *! *! If everything went fine, a call to @[errno()] directly afterwards
5601732004-11-30Martin Stjernholm  *! returns zero.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
5601732004-11-30Martin Stjernholm  *! If more than one argument is given, @[sprintf()] is used to format *! them.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @note
5601732004-11-30Martin Stjernholm  *! It is not guaranteed that all out-of-band data sent from the *! other end is received. Most streams only allow for a single byte *! of out-of-band data at a time. Some streams sends the rest of *! the data as ordinary data.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @seealso *! @[read_oob()], @[write()] */
c201101998-03-25Henrik Grubbström (Grubba) static void file_write_oob(INT32 args) {
cbe0212000-08-19Henrik Grubbström (Grubba)  ptrdiff_t written, i;
c201101998-03-25Henrik Grubbström (Grubba)  struct pike_string *str;
017b572011-10-28Henrik Grubbström (Grubba)  if(args<1 || TYPEOF(Pike_sp[-args]) != PIKE_T_STRING)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("write_oob",1,"string");
c201101998-03-25Henrik Grubbström (Grubba)  if(args > 1) { f_sprintf(args); args=1; } if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open for write_oob.\n");
ee71702000-01-30Per Hedbor 
c201101998-03-25Henrik Grubbström (Grubba)  written=0;
5923b12000-07-06Fredrik Hübinette (Hubbe)  str=Pike_sp[-args].u.string;
7040d02001-01-16Fredrik Hübinette (Hubbe)  if(str->size_shift) Pike_error("Stdio.File->write_oob(): cannot output wide strings.\n");
c201101998-03-25Henrik Grubbström (Grubba)  while(written < str->len) { int fd=FD;
700dac2002-02-05Martin Stjernholm  int e;
c201101998-03-25Henrik Grubbström (Grubba)  THREADS_ALLOW();
b96ca92000-08-19Henrik Grubbström (Grubba)  i = fd_send(fd, str->str + written, str->len - written, MSG_OOB);
ae39322003-09-30Martin Stjernholm  e=errno;
c201101998-03-25Henrik Grubbström (Grubba)  THREADS_DISALLOW();
700dac2002-02-05Martin Stjernholm  check_threads_etc();
c201101998-03-25Henrik Grubbström (Grubba) #ifdef _REENTRANT
ac6cf82009-04-23Martin Stjernholm  if(FD<0) Pike_error("File closed while in file->write_oob.\n");
c201101998-03-25Henrik Grubbström (Grubba) #endif if(i<0) {
700dac2002-02-05Martin Stjernholm  switch(e)
c201101998-03-25Henrik Grubbström (Grubba)  { default:
ae39322003-09-30Martin Stjernholm  ERRNO=errno=e;
c201101998-03-25Henrik Grubbström (Grubba)  pop_n_elems(args);
4451331999-04-01Henrik Grubbström (Grubba)  if (!written) { push_int(-1); } else {
cbe0212000-08-19Henrik Grubbström (Grubba)  push_int64(written);
4451331999-04-01Henrik Grubbström (Grubba)  }
31b7752005-01-27Martin Stjernholm  /* Minor race - see below. */ THIS->box.revents &= ~(PIKE_BIT_FD_WRITE|PIKE_BIT_FD_WRITE_OOB);
c201101998-03-25Henrik Grubbström (Grubba)  return; case EINTR: continue; case EWOULDBLOCK: break; } break; }else{ written+=i; /* Avoid extra write() */ if(THIS->open_mode & FILE_NONBLOCKING) break; } }
31b7752005-01-27Martin Stjernholm  /* Race: A backend in another thread might have managed to set these * again for buffer space available after the write above. Not that * bad - it will get through in a later backend round. */ THIS->box.revents &= ~(PIKE_BIT_FD_WRITE|PIKE_BIT_FD_WRITE_OOB);
10dac82004-04-05Martin Stjernholm  if(!SAFE_IS_ZERO(& THIS->event_cbs[PIKE_FD_WRITE_OOB])) ADD_FD_EVENTS (THIS, PIKE_BIT_FD_WRITE_OOB);
c201101998-03-25Henrik Grubbström (Grubba)  ERRNO=0;
f010202011-11-16Tobias S. Josefowitz  if (!(THIS->open_mode & FILE_NONBLOCKING)) INVALIDATE_CURRENT_TIME();
c201101998-03-25Henrik Grubbström (Grubba)  pop_n_elems(args);
cbe0212000-08-19Henrik Grubbström (Grubba)  push_int64(written);
c201101998-03-25Henrik Grubbström (Grubba) }
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD /*! @decl void send_fd(Stdio.Fd fd) *! *! Queues an open file descriptor for sending to the other end of a stream. *! *! @note *! The actual sending is performed at the next successful call *! to @[write()], this is due to limitations in the system calls. *! This means that it isn't possible to send a file descriptor *! without also sending some in-band data. *! *! This operation is only supported on @[pipe()]'s created with *! @[PROP_SEND_FD]. *! *! This function is not available on all operating systems, check *! for @[__HAVE_SEND_FD__]. *! *! The queue is emptied on successful @[write()] and when the *! write direction is @[close()]'d. *! *! @seealso *! @[receive_fd()], @[write()], @[pipe()], @[read()], @[__HAVE_SEND_FD__] */ static void file_send_fd(INT32 args) { int other_fd; struct object *o = NULL; struct my_file *f = NULL; int *fd_info = NULL;
017b572011-10-28Henrik Grubbström (Grubba)  if(args<1 || (TYPEOF(Pike_sp[-args]) != PIKE_T_OBJECT) ||
f126b62010-11-19Henrik Grubbström (Grubba)  !(o = Pike_sp[-args].u.object)->prog ||
017b572011-10-28Henrik Grubbström (Grubba)  (o->prog->inherits[SUBTYPEOF(Pike_sp[-args])].prog != file_program))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("send_fd", 1, "Stdio.Fd");
f126b62010-11-19Henrik Grubbström (Grubba)  f = (struct my_file *)
017b572011-10-28Henrik Grubbström (Grubba)  (o->storage + o->prog->inherits[SUBTYPEOF(Pike_sp[-args])].storage_offset);
f126b62010-11-19Henrik Grubbström (Grubba)  if (f->box.fd == -1) { Pike_error("Bad argument 1 to Stdio.File->send_fd(): " "File descriptor not open.\n"); } if(FD < 0) Pike_error("File not open for write.\n"); if (!(THIS->open_mode & fd_SEND_FD)) Pike_error("send_fd() not supported on this file.\n"); if (!(fd_info = THIS->fd_info) || (fd_info[0] == fd_info[1]+2)) { int *fds; if (fd_info) { fds = realloc(fd_info, fd_info[0]*2*sizeof(int)); if (fds) fds[0] *= 2; } else { fds = malloc(8*sizeof(int)); if (fds) { fds[0] = 8; fds[1] = 0; } } if (!fds) Pike_error("Out of memory.\n"); THIS->fd_info = fd_info = fds; #ifdef PIKE_DEBUG /* Note: Unusual range. */
5c7b532014-02-26Arne Goedeke  { int e; for (e = fds[0]-2; e > fds[1]; e--) { fds[e + 1] = -1; }
f126b62010-11-19Henrik Grubbström (Grubba)  } #endif } do { other_fd = dup(f->box.fd);
5344ae2012-12-02Peter Bortas  } while((other_fd < 0) && (errno == EINTR));
f126b62010-11-19Henrik Grubbström (Grubba)  if (other_fd < 0) { Pike_error("Out of file descriptors.\n"); } fd_info[2 + fd_info[1]++] = other_fd; } #endif
a8685d2013-05-29Henrik Grubbström (Grubba) #ifdef SO_LINGER /*! @decl int(0..1) linger(int(-1..65535)|void seconds) *! *! Set the socket linger behaviour on @[close()]. *! *! @param seconds *! @int *! @value -1 *! Reset to default behaviour. This typically means that *! @[close()] will return immediately, but any buffered *! data will still be sent if possible. *! @value 0 *! Terminate the connection immediately on @[close()], *! and discard any buffered data. *! @value 1..65535 *! Have @[close()] wait for at most @[seconds] seconds *! for any buffered data to be sent after which the *! connection is terminated. *! @endint *! *! @returns *! Returns @expr{1@} on success, and @expr{0@} (zero) on failure. *! *! @note *! This operation is only valid on sockets. *! *! @note *! This function was not available in Pike 7.8.775 and earlier. *! *! @seealso *! @[close()] */ static void file_linger(INT32 args) { int fd = FD; int linger = -1; struct linger li; if(fd < 0) Pike_error("File not open.\n");
69c0aa2014-08-25Martin Nilsson  get_all_args("linger", args, ".%d", &linger);
a8685d2013-05-29Henrik Grubbström (Grubba)  if ((linger < -1) || (linger > 0xffff)) {
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("linger", 1, "int(-1..65535)");
a8685d2013-05-29Henrik Grubbström (Grubba)  } if (linger == -1) { li.l_onoff = 0; li.l_linger = 15; } else { li.l_onoff = 1; li.l_linger = linger; } while ((fd_setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&li, sizeof(li)) < 0) && (errno == EINTR)) { errno = 0; } if (errno) { ERRNO = errno; push_int(0); } else { push_int(1); } } #endif
5fe4f72013-12-06Chris Angelico #ifdef TCP_NODELAY /*! @decl int(0..1) set_nodelay(int(0..1)|void state) *! *! Control Nagle's Algorithm (RFC 896) *! *! @param state *! @int *! @value 0 *! Return to the normal state of using Nagle's Algorithm *! @value 1 *! (default) Disable Nagling - small writes will not be queued. *! @endint *! *! @returns *! Returns @expr{1@} on success, and @expr{0@} (zero) on failure. *! *! @note *! This operation is only valid on sockets. *! *! @seealso *! setsockopt() */ static void file_nodelay(INT32 args) { int fd = FD; int state = 1; if(fd < 0) Pike_error("File not open.\n"); get_all_args("set_nodelay", args, ".%d", &state); if (state && state != 1) { SIMPLE_BAD_ARG_ERROR("set_nodelay()", 1, "int(0..1)"); } errno = 0; while ((fd_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state)) < 0) && (errno == EINTR)) { errno = 0; } if (errno) { ERRNO = errno; push_int(0); } else { push_int(1); } } #endif
a1ef721998-04-05Fredrik Hübinette (Hubbe) static int do_close(int flags)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
10dac82004-04-05Martin Stjernholm  struct my_file *f = THIS;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(FD == -1) return 1; /* already closed */ ERRNO=0;
83a7641996-12-15Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  flags &= f->open_mode;
2acdd31995-10-29Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(flags & (FILE_READ | FILE_WRITE)) { case 0:
83a7641996-12-15Fredrik Hübinette (Hubbe)  return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case FILE_READ:
10dac82004-04-05Martin Stjernholm  if(f->open_mode & FILE_WRITE)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
ca6bd02012-05-01Bill Welliver  SUB_FD_EVENTS (f, PIKE_BIT_FD_READ|PIKE_BIT_FD_READ_OOB|PIKE_BIT_FD_FS_EVENT);
a1ef721998-04-05Fredrik Hübinette (Hubbe)  fd_shutdown(FD, 0);
10dac82004-04-05Martin Stjernholm  f->open_mode &=~ FILE_READ;
83a7641996-12-15Fredrik Hübinette (Hubbe)  return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
10dac82004-04-05Martin Stjernholm  f->flags&=~FILE_NOT_OPENED;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  close_fd();
83a7641996-12-15Fredrik Hübinette (Hubbe)  return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } case FILE_WRITE:
10dac82004-04-05Martin Stjernholm  if(f->open_mode & FILE_READ)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
ca6bd02012-05-01Bill Welliver  SUB_FD_EVENTS (f, PIKE_BIT_FD_WRITE|PIKE_BIT_FD_WRITE_OOB|PIKE_BIT_FD_FS_EVENT);
a1ef721998-04-05Fredrik Hübinette (Hubbe)  fd_shutdown(FD, 1);
10dac82004-04-05Martin Stjernholm  f->open_mode &=~ FILE_WRITE;
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (f->fd_info) do_close_fd_info(f->fd_info); #endif
83a7641996-12-15Fredrik Hübinette (Hubbe)  return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
10dac82004-04-05Martin Stjernholm  f->flags&=~FILE_NOT_OPENED;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  close_fd();
83a7641996-12-15Fredrik Hübinette (Hubbe)  return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } case FILE_READ | FILE_WRITE:
10dac82004-04-05Martin Stjernholm  f->flags&=~FILE_NOT_OPENED;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  close_fd();
83a7641996-12-15Fredrik Hübinette (Hubbe)  return 1; default:
5aad932002-08-15Marcus Comstedt  Pike_fatal("Bug in switch implementation!\n");
9282fd2015-09-27Martin Nilsson  UNREACHABLE(return 0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
eddb642002-11-09Per Hedbor /*! @decl string grantpt() *!
0e49202003-05-15Marcus Comstedt  *! If this file has been created by calling @[openpt()], return the
eddb642002-11-09Per Hedbor  *! filename of the associated pts-file. This function should only be *! called once.
00fa4a2003-09-30Martin Nilsson  *!
8369082013-11-13Henrik Grubbström (Grubba)  *! @returns *! Returns the filename of the corresponding pts. *!
00fa4a2003-09-30Martin Nilsson  *! @note *! This function is only available on some platforms.
eddb642002-11-09Per Hedbor  */
00fa4a2003-09-30Martin Nilsson #if defined(HAVE_GRANTPT) || defined(USE_PT_CHMOD) || defined(USE_CHGPT)
eddb642002-11-09Per Hedbor static void file_grantpt( INT32 args ) { pop_n_elems(args);
9b25612003-07-03Henrik Grubbström (Grubba) #if defined(USE_PT_CHMOD) || defined(USE_CHGPT)
5e9fc02015-08-18Per Hedbor  push_static_text("Process.Process");
da2e892003-05-14Marcus Comstedt  APPLY_MASTER("resolv", 1);
e296562003-07-03Henrik Grubbström (Grubba) 
9b25612003-07-03Henrik Grubbström (Grubba) #ifdef USE_PT_CHMOD /* pt_chmod wants to get the fd number as the first argument. */
7cf0162014-05-22Per Hedbor  push_text(USE_PT_CHMOD);
5e9fc02015-08-18Per Hedbor  push_static_text("4");
da2e892003-05-14Marcus Comstedt  f_aggregate(2);
e296562003-07-03Henrik Grubbström (Grubba) 
9b25612003-07-03Henrik Grubbström (Grubba)  /* Send the pty as both fd 3 and fd 4. */
5e9fc02015-08-18Per Hedbor  push_static_text("fds");
da2e892003-05-14Marcus Comstedt  ref_push_object(Pike_fp->current_object); ref_push_object(Pike_fp->current_object); f_aggregate(2);
9b25612003-07-03Henrik Grubbström (Grubba)  f_aggregate_mapping(2); #else /* USE_CHGPT */ /* chgpt on HPUX doesn't like getting any arguments... */
7cf0162014-05-22Per Hedbor  push_text(USE_CHGPT);
c8e7cb2003-07-05Henrik Grubbström (Grubba)  f_aggregate(1);
e296562003-07-03Henrik Grubbström (Grubba) 
9b25612003-07-03Henrik Grubbström (Grubba)  /* chgpt wants to get the pty on fd 0. */
5e9fc02015-08-18Per Hedbor  push_static_text("stdin");
47f5d32003-07-02Henrik Grubbström (Grubba)  ref_push_object(Pike_fp->current_object);
9b25612003-07-03Henrik Grubbström (Grubba)  f_aggregate_mapping(2); #endif /* USE_PT_CHMOD */
e296562003-07-03Henrik Grubbström (Grubba) 
da2e892003-05-14Marcus Comstedt  apply_svalue(Pike_sp-3, 2); apply(Pike_sp[-1].u.object, "wait", 0);
f583a42003-07-04Henrik Grubbström (Grubba)  if(!UNSAFE_IS_ZERO(Pike_sp-1)) { Pike_error(
434deb2003-07-05Henrik Grubbström (Grubba) #ifdef USE_PT_CHMOD
f583a42003-07-04Henrik Grubbström (Grubba)  USE_PT_CHMOD #else /* USE_CHGPT */ USE_CHGPT #endif /* USE_PT_CHMOD */ " returned error %d.\n", Pike_sp[-1].u.integer); }
da2e892003-05-14Marcus Comstedt  pop_n_elems(3);
9b25612003-07-03Henrik Grubbström (Grubba) #else /* HAVE_GRANTPT */
8369082013-11-13Henrik Grubbström (Grubba)  /* Make sure the fd doesn't get closed when it gets sent * to the subprocess (aka /usr/lib/pt_chmod). */ set_close_on_exec(FD, 0);
eddb642002-11-09Per Hedbor  if( grantpt( FD ) ) Pike_error("grantpt failed: %s\n", strerror(errno));
8369082013-11-13Henrik Grubbström (Grubba)  set_close_on_exec(FD, 1);
9b25612003-07-03Henrik Grubbström (Grubba) #endif /* USE_PT_CHMOD || USE_CHGPT */
eddb642002-11-09Per Hedbor  push_text( ptsname( FD ) );
00fa4a2003-09-30Martin Nilsson #ifdef HAVE_UNLOCKPT
eddb642002-11-09Per Hedbor  if( unlockpt( FD ) ) Pike_error("unlockpt failed: %s\n", strerror(errno)); #endif }
00fa4a2003-09-30Martin Nilsson #endif /* HAVE_GRANTPT || USE_PT_CHMOD || USE_CHGPT */
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int close() *! @decl int close(string direction) *! *! Close a file or stream. *!
5601732004-11-30Martin Stjernholm  *! If direction is not specified, both the read and the write *! direction is closed. Otherwise only the directions specified is *! closed.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
1b5eb42003-10-15Martin Stjernholm  *! @returns *! Nonzero is returned if the file or stream wasn't open in the *! specified direction, zero otherwise. *!
f53cc02003-10-15Martin Stjernholm  *! @throws *! An exception is thrown if an I/O error occurs. *!
a8685d2013-05-29Henrik Grubbström (Grubba)  *! The default behaviour for sockets is typically to flush buffered *! data in the background, but this can be changed with @[linger()]. *!
f53cc02003-10-15Martin Stjernholm  *! @note *! @[close()] has no effect if this file object has been associated *! with an already opened file, i.e. if @[open()] was given an *! integer as the first argument. *!
9c052f2001-02-15Henrik Grubbström (Grubba)  *! @seealso
a8685d2013-05-29Henrik Grubbström (Grubba)  *! @[linger()], @[open()], @[open_socket()]
9c052f2001-02-15Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_close(INT32 args) { int flags; if(args) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad argument 1 to file->close()\n");
5923b12000-07-06Fredrik Hübinette (Hubbe)  flags=parse(Pike_sp[-args].u.string->str);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ flags=FILE_READ | FILE_WRITE; }
ae9b441999-04-20Henrik Grubbström (Grubba)  if (THIS->flags & FILE_LOCK_FD) {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("close() has been temporarily disabled on this file.\n");
ae9b441999-04-20Henrik Grubbström (Grubba)  }
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if((THIS->open_mode & ~flags & (FILE_READ|FILE_WRITE)) && flags)
bcf9461998-01-27Fredrik Hübinette (Hubbe)  {
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(!(THIS->open_mode & fd_CAN_SHUTDOWN))
bcf9461998-01-27Fredrik Hübinette (Hubbe)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot close one direction on this file.\n");
bcf9461998-01-27Fredrik Hübinette (Hubbe)  } }
a1ef721998-04-05Fredrik Hübinette (Hubbe)  flags=do_close(flags);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
a1ef721998-04-05Fredrik Hübinette (Hubbe)  push_int(flags);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1053be2001-11-22Martin Nilsson /*! @decl int open(string filename, string mode) *! @decl int open(string filename, string mode, int access) *! @decl int open(int fd, string mode) *!
f53cc02003-10-15Martin Stjernholm  *! Open a file, or use an existing fd. *! *! If @[filename] is given, attempt to open the named file. If @[fd] *! is given instead, it should be the file descriptor for an already *! opened file, which will then be used by this object. *!
5601732004-11-30Martin Stjernholm  *! @[mode] describes how the file is opened. It's a case-insensitive *! string consisting of one or more of the following letters:
f53cc02003-10-15Martin Stjernholm  *! *! @dl *! @item "r" *! Open for reading. *! @item "w" *! Open for writing. *! @item "a" *! Append new data to the end. *! @item "c" *! Create the file if it doesn't exist already. *! @item "t" *! Truncate the file to zero length if it already contains data. *! Use only together with @expr{"w"@}. *! @item "x"
5601732004-11-30Martin Stjernholm  *! Open exclusively - the open fails if the file already exists. *! Use only together with @expr{"c"@}. Note that it's not safe to *! assume that this is atomic on some systems.
f53cc02003-10-15Martin Stjernholm  *! @enddl *! *! @[access] specifies the permissions to use if a new file is *! created. It is a UNIX style permission bitfield: *! *! @dl *! @item 0400 *! User has read permission. *! @item 0200 *! User has write permission. *! @item 0100 *! User has execute permission. *! @item 0040 *! Group has read permission. *! @item 0020 *! Group has write permission. *! @item 0010 *! Group has execute permission. *! @item 0004 *! Others have read permission. *! @item 0002 *! Others have write permission. *! @item 0001 *! Others have execute permission. *! @enddl
1053be2001-11-22Martin Nilsson  *!
f53cc02003-10-15Martin Stjernholm  *! It's system dependent on which of these bits that are actually
5601732004-11-30Martin Stjernholm  *! heeded. If @[access] is not specified, it defaults to
f53cc02003-10-15Martin Stjernholm  *! @expr{00666@}, but note that on UNIX systems it's masked with the *! process umask before use.
1053be2001-11-22Martin Nilsson  *!
8aaf0e2008-09-05Martin Stjernholm  *! @returns *! Returns nonzero on success and @expr{0@} (zero) on failure. If *! there is a failure then @[errno] returns the error code. *!
1053be2001-11-22Martin Nilsson  *! @seealso *! @[close()]
9c052f2001-02-15Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_open(INT32 args) { int flags,fd;
779b491997-06-25Niels Möller  int access;
ae39322003-09-30Martin Stjernholm  int err;
c51fb71999-02-01Henrik Grubbström (Grubba)  struct pike_string *str, *flag_str;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  close_fd();
ee71702000-01-30Per Hedbor 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(args < 2)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("open", 2);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_STRING && TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("open", 1, "string|int");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[1-args]) != PIKE_T_STRING)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("open", 2, "string");
07513e1996-10-04Fredrik Hübinette (Hubbe) 
779b491997-06-25Niels Möller  if (args > 2) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[2-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("open", 3, "int");
5923b12000-07-06Fredrik Hübinette (Hubbe)  access = Pike_sp[2-args].u.integer;
779b491997-06-25Niels Möller  } else access = 00666;
7e97c31999-01-21Fredrik Hübinette (Hubbe) 
5923b12000-07-06Fredrik Hübinette (Hubbe)  flags = parse((flag_str = Pike_sp[1-args].u.string)->str);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-args]) == PIKE_T_STRING)
7e97c31999-01-21Fredrik Hübinette (Hubbe)  {
5923b12000-07-06Fredrik Hübinette (Hubbe)  str=Pike_sp[-args].u.string;
7e97c31999-01-21Fredrik Hübinette (Hubbe) 
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str)) {
76d9522000-08-23Henrik Grubbström (Grubba)  /* Filenames with NUL are not supported. */
ae39322003-09-30Martin Stjernholm  ERRNO = errno = ENOENT;
76d9522000-08-23Henrik Grubbström (Grubba)  pop_n_elems(args); push_int(0); return;
8c7a452000-07-21Henrik Grubbström (Grubba)  }
c9a7461999-09-29Mirar (Pontus Hagland)  if(!( flags & (FILE_READ | FILE_WRITE)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Must open file for at least one of read and write.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
c9a7461999-09-29Mirar (Pontus Hagland)  do {
00f1d92000-04-14Henrik Grubbström (Grubba)  THREADS_ALLOW_UID(); fd=fd_open(str->str,map(flags), access);
ae39322003-09-30Martin Stjernholm  err = errno;
00f1d92000-04-14Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID();
ae39322003-09-30Martin Stjernholm  if ((fd < 0) && (err == EINTR))
00f1d92000-04-14Henrik Grubbström (Grubba)  check_threads_etc();
ae39322003-09-30Martin Stjernholm  } while(fd < 0 && err == EINTR);
07513e1996-10-04Fredrik Hübinette (Hubbe) 
5923b12000-07-06Fredrik Hübinette (Hubbe)  if(!Pike_fp->current_object->prog)
5b793f2000-04-03Fredrik Hübinette (Hubbe)  {
00f1d92000-04-14Henrik Grubbström (Grubba)  if (fd >= 0)
ae39322003-09-30Martin Stjernholm  while (fd_close(fd) && errno == EINTR) {}
b1c4582003-01-11Martin Nilsson  Pike_error("Object destructed in Stdio.File->open()\n");
5b793f2000-04-03Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b80e8b2000-05-20Per Hedbor  if(fd < 0)
c9a7461999-09-29Mirar (Pontus Hagland)  {
ae39322003-09-30Martin Stjernholm  ERRNO=errno=err;
c9a7461999-09-29Mirar (Pontus Hagland)  } else {
41d7dc2007-05-20Henrik Grubbström (Grubba)  init_fd(fd, flags | fd_query_properties(fd, FILE_CAPABILITIES), 0);
c9a7461999-09-29Mirar (Pontus Hagland)  set_close_on_exec(fd,1); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } else {
5923b12000-07-06Fredrik Hübinette (Hubbe)  fd=Pike_sp[-args].u.integer;
b80e8b2000-05-20Per Hedbor  if (fd<0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Not a valid FD.\n");
c9a7461999-09-29Mirar (Pontus Hagland) 
41d7dc2007-05-20Henrik Grubbström (Grubba)  /* FIXME: What are the intended semantics for the flag FILE_NOT_OPENED?
03ae602004-09-01Henrik Grubbström (Grubba)  * (grubba 2004-09-01 */
7363b72011-09-07Henrik Grubbström (Grubba)  init_fd(fd, flags | low_fd_query_properties(fd), FILE_NOT_OPENED);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } pop_n_elems(args); push_int(fd>=0); }
deee412008-02-19Henrik Grubbström (Grubba) #ifdef HAVE_OPENAT /*! @decl Stdio.File openat(string filename, string mode) *! @decl Stdio.File openat(string filename, string mode, int access) *! *! Open a file relative to an opened directory. *! *! @returns
09ebad2008-03-26Martin Bähr  *! Returns a new file object on success, and @expr{0@} (zero) on failure.
deee412008-02-19Henrik Grubbström (Grubba)  *! *! @note
e1aec82014-11-15Stephen R. van den Berg  *! Not available on all architectures.
deee412008-02-19Henrik Grubbström (Grubba)  *! *! @seealso
18a5112008-03-14Henrik Grubbström (Grubba)  *! @[open()], @[statat()], @[unlinkat()]
deee412008-02-19Henrik Grubbström (Grubba)  */ static void file_openat(INT32 args) { int flags, fd, dir_fd; int access = 00666; int err; struct pike_string *str, *flag_str; if((dir_fd = FD) < 0) Pike_error("File not open.\n");
69c0aa2014-08-25Martin Nilsson  get_all_args("openat", args, "%S%S.%d", &str, &flag_str, &access);
deee412008-02-19Henrik Grubbström (Grubba)  flags = parse(flag_str->str); if (string_has_null(str)) { /* Filenames with NUL are not supported. */ ERRNO = errno = ENOENT; pop_n_elems(args); push_int(0); return; } if(!(flags & (FILE_READ | FILE_WRITE))) Pike_error("Must open file for at least one of read and write.\n"); do { THREADS_ALLOW_UID(); fd = openat(dir_fd, str->str, map(flags), access); err = errno; THREADS_DISALLOW_UID(); if ((fd < 0) && (err == EINTR)) check_threads_etc(); } while(fd < 0 && err == EINTR); if(fd < 0) { ERRNO=errno=err; pop_n_elems(args); push_int(0); } else {
da7e5d2009-02-23Henrik Grubbström (Grubba)  push_new_fd_object(fd_fd_factory_fun_num, fd, flags, FILE_CAPABILITIES);
deee412008-02-19Henrik Grubbström (Grubba)  set_close_on_exec(fd, 1); stack_pop_n_elems_keep_top(args); } } #endif /* HAVE_OPENAT */
0e49202003-05-15Marcus Comstedt #if !defined(__NT__) && (defined(HAVE_POSIX_OPENPT) || defined(PTY_MASTER_PATHNAME)) /*! @decl int openpt(string mode) *! *! Open the master end of a pseudo-terminal pair. *!
2c65362004-04-05Martin Stjernholm  *! @returns *! This function returns @expr{1@} for success, @expr{0@} otherwise. *!
0e49202003-05-15Marcus Comstedt  *! @seealso *! @[grantpt()] */ static void file_openpt(INT32 args) { int flags,fd;
dfafa92003-09-01Martin Nilsson #ifdef HAVE_POSIX_OPENPT
0e49202003-05-15Marcus Comstedt  struct pike_string *flag_str;
dfafa92003-09-01Martin Nilsson #endif
0e49202003-05-15Marcus Comstedt  close_fd(); if(args < 1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("openpt", 1);
0e49202003-05-15Marcus Comstedt 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_STRING)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("openpt", 1, "string");
0e49202003-05-15Marcus Comstedt  #ifdef HAVE_POSIX_OPENPT
860d182003-05-15Marcus Comstedt  flags = parse((flag_str = Pike_sp[-args].u.string)->str);
13670c2015-05-25Martin Nilsson 
0e49202003-05-15Marcus Comstedt  if(!( flags & (FILE_READ | FILE_WRITE))) Pike_error("Must open file for at least one of read and write.\n"); do { THREADS_ALLOW_UID(); fd=posix_openpt(map(flags)); THREADS_DISALLOW_UID(); if ((fd < 0) && (errno == EINTR)) check_threads_etc(); } while(fd < 0 && errno == EINTR); if(!Pike_fp->current_object->prog) { if (fd >= 0)
ae39322003-09-30Martin Stjernholm  while (fd_close(fd) && errno == EINTR) {} Pike_error("Object destructed in Stdio.File->openpt()\n");
0e49202003-05-15Marcus Comstedt  } if(fd < 0) { ERRNO=errno; } else {
41d7dc2007-05-20Henrik Grubbström (Grubba)  init_fd(fd, flags | fd_query_properties(fd, FILE_CAPABILITIES), 0);
0e49202003-05-15Marcus Comstedt  set_close_on_exec(fd,1); } pop_n_elems(args); push_int(fd>=0); #else if(args > 1) pop_n_elems(args - 1);
7cf0162014-05-22Per Hedbor  push_text(PTY_MASTER_PATHNAME);
0e49202003-05-15Marcus Comstedt  stack_swap(); file_open(2); #endif } #endif
02e2012001-06-25Henrik Grubbström (Grubba) #ifdef HAVE_FSYNC /*! @decl int(0..1) sync() *! *! Flush buffers to disk. *! *! @returns *!
cbe8c92003-04-07Martin Nilsson  *! Returns @expr{0@} (zero) and sets errno on failure.
02e2012001-06-25Henrik Grubbström (Grubba)  *!
cbe8c92003-04-07Martin Nilsson  *! Returns @expr{1@} on success.
02e2012001-06-25Henrik Grubbström (Grubba)  */ void file_sync(INT32 args) { int ret;
700dac2002-02-05Martin Stjernholm  int fd = FD; int e;
02e2012001-06-25Henrik Grubbström (Grubba) 
700dac2002-02-05Martin Stjernholm  if(fd < 0)
02e2012001-06-25Henrik Grubbström (Grubba)  Pike_error("File not open.\n"); pop_n_elems(args); do {
700dac2002-02-05Martin Stjernholm  THREADS_ALLOW(); ret = fsync(fd); e = errno; THREADS_DISALLOW(); check_threads_etc(); } while ((ret < 0) && (e == EINTR));
02e2012001-06-25Henrik Grubbström (Grubba)  if (ret < 0) {
ae39322003-09-30Martin Stjernholm  ERRNO = errno = e;
02e2012001-06-25Henrik Grubbström (Grubba)  push_int(0); } else { push_int(1); } } #endif /* HAVE_FSYNC */
9a70222016-02-11Martin Nilsson #if (defined(HAVE_LSEEK64) || defined(__NT__))
eba4c52005-03-10Martin Nilsson #define SEEK64 #endif
707b922014-09-23Per Hedbor  /*! @decl int seek(int offset) *! @decl int seek(int offset, string whence) *! *! The seek() function repositions the offset of the open file *! associated with the file descriptor fd to the argument @[offset] *! according to the directive @[whence] as follows: *! *! @string *! @value Stdio.SEEK_SET *! The offset is set to @[offset] bytes. *! @value Stdio.SEEK_CUR *! The offset is set to its current location plus @[offset] bytes. *! @value Stdio.SEEK_END *! The offset is set to the size of the file plus @[offset] bytes. *! @endstring *! *! If @[whence] is not specified it is SEEK_SET if @[offset] is *! positive, and if @[offset] is negative SEEK_END. *! *! The seek() function on most operating systems allows the file *! offset to be set beyond the end of the file (but this does not *! change the size of the file). If data is later written at this *! point, subsequent reads of the data in the gap (a "hole") return *! null bytes ('\0') until data is actually written into the gap. *! *! Seeking file data and holes *! *! Stdio.SEEK_DATA and Stdio.SEEK_HOLE are nonstandard extensions *! present in Linux, Solaris, FreeBSD, and DragonFly BSD; they are *! proposed for inclusion in the next POSIX revision. *! @string *! @value Stdio.SEEK_DATA *! Adjust the file offset to the next location in the file greater *! than or equal to offset containing data. If offset points to *! data, then the file offset is set to offset. *! *! @value Stdio.SEEK_HOLE *! Adjust the file offset to the next hole in the file greater than *! or equal to offset. If offset points into the middle of a hole, *! then the file offset is set to offset. If there is no hole past *! offset, then the file offset is adjusted to the end of the file *! (i.e., there is an implicit hole at the end of any file). *! @endstring *! *! In both of the above cases, seek() fails if offset points past the *! end of the file. *! *! These operations allow applications to map holes in a sparsely *! allocated file. This can be useful for applications such as file *! backup tools, which can save space when creating backups and *! preserve holes, if they have a mechanism for discovering holes. *! *! For the purposes of these operations, a hole is a sequence of *! zeros that (normally) has not been allocated in the underlying *! file storage. However, a filesystem is not obliged to report *! holes, so these operations are not a guaranteed mechanism for *! mapping the storage space actually allocated to a file. *! (Furthermore, a sequence of zeros that actually has been written *! to the underlying storage may or may not be reported as a hole.) *! *! In the simplest implementation, a filesystem can support the *! operations by making SEEK_HOLE always return the offset of the end *! of the file, and making SEEK_DATA always return offset (i.e., even *! if the location referred to by offset is a hole, it can be *! considered to consist of data that is a sequence of zeros).
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @returns
707b922014-09-23Per Hedbor  *! Upon successful completion, seek() returns the resulting offset *! location as measured in bytes from the beginning of the file. On *! error, the value (off_t) -1 is returned and @[errno] is set to *! indicate the error.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @seealso *! @[tell()] */
707b922014-09-23Per Hedbor  /* * @decl deprecated variant int seek(int unit, int mult) * @decl deprecated variant int seek(int unit, int mult, int add) * * Seek to a specified offset in a file. * * If @[mult] or @[add] are specified, @[pos] is calculated as * @expr{@[pos] = @[unit]*@[mult] + @[add]@}. * * If @[pos] is negative then it is relative to the end of the file, * otherwise it's an absolute offset from the start of the file. * * @returns * Returns the new offset, or @expr{-1@} on failure. * * @note * The arguments @[mult] and @[add] are considered obsolete, and * should not be used. * * @seealso * @[tell()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_seek(INT32 args) {
eba4c52005-03-10Martin Nilsson #ifdef SEEK64
36a00c2000-08-15Henrik Grubbström (Grubba)  INT64 to = 0;
a12e961998-03-22Per Hedbor #else
f202eb2003-03-28Martin Stjernholm  off_t to = 0;
2fe5651999-10-29Fredrik Noring #endif
707b922014-09-23Per Hedbor  int how = SEEK_SET;
ee71702000-01-30Per Hedbor 
b1c4582003-01-11Martin Nilsson  if( args < 1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("seek", 1);
f202eb2003-03-28Martin Stjernholm 
0311712013-06-17Martin Nilsson #if defined (SEEK64)
f202eb2003-03-28Martin Stjernholm  if(is_bignum_object_in_svalue(&Pike_sp[-args])) { if (!int64_from_bignum(&to, Pike_sp[-args].u.object)) Pike_error ("Bad argument 1 to Stdio.File->seek(). Offset too large.\n"); }
2fe5651999-10-29Fredrik Noring  else
f202eb2003-03-28Martin Stjernholm #endif
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("seek", 1, "int");
f202eb2003-03-28Martin Stjernholm  else to=Pike_sp[-args].u.integer;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
a12e961998-03-22Per Hedbor 
707b922014-09-23Per Hedbor  if( args == 2 && TYPEOF(Pike_sp[-args+1]) == PIKE_T_STRING )
a12e961998-03-22Per Hedbor  {
707b922014-09-23Per Hedbor  how = Pike_sp[-args+1].u.string->str[0];
a12e961998-03-22Per Hedbor  }
707b922014-09-23Per Hedbor  else
a12e961998-03-22Per Hedbor  {
707b922014-09-23Per Hedbor  if(args>1) { if(TYPEOF(Pike_sp[-args+1]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("seek", 2, "int");
707b922014-09-23Per Hedbor  to *= Pike_sp[-args+1].u.integer; } if(args>2) { if(TYPEOF(Pike_sp[-args+2]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("seek", 3, "int");
707b922014-09-23Per Hedbor  to += Pike_sp[-args+2].u.integer; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
707b922014-09-23Per Hedbor  if( to < 0 ) how = SEEK_END; }
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
eba4c52005-03-10Martin Nilsson #if defined(HAVE_LSEEK64) && !defined(__NT__)
707b922014-09-23Per Hedbor  to = lseek64(FD,to,how);
a12e961998-03-22Per Hedbor #else
707b922014-09-23Per Hedbor  to = fd_lseek(FD,to,how);
a12e961998-03-22Per Hedbor #endif
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(to<0) ERRNO=errno;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
2fe5651999-10-29Fredrik Noring  push_int64(to);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
9a70222016-02-11Martin Nilsson #if (defined(HAVE_LSEEK64) || defined(__NT__))
d584222005-03-10Martin Nilsson #define TELL64 #endif
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int tell() *! *! Returns the current offset in the file. *! *! @seealso *! @[seek()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_tell(INT32 args) {
d584222005-03-10Martin Nilsson #ifdef TELL64
2fe5651999-10-29Fredrik Noring  INT64 to; #else
f202eb2003-03-28Martin Stjernholm  off_t to;
2fe5651999-10-29Fredrik Noring #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
ee71702000-01-30Per Hedbor 
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
d584222005-03-10Martin Nilsson  #if defined(HAVE_LSEEK64) && !defined(__NT__)
b96ca92000-08-19Henrik Grubbström (Grubba)  to = lseek64(FD, 0L, SEEK_CUR);
2fe5651999-10-29Fredrik Noring #else
b96ca92000-08-19Henrik Grubbström (Grubba)  to = fd_lseek(FD, 0L, SEEK_CUR);
2fe5651999-10-29Fredrik Noring #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(to<0) ERRNO=errno;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
2fe5651999-10-29Fredrik Noring  push_int64(to);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int(0..1) truncate(int length) *! *! Truncate a file. *! *! Truncates the file to the specified length @[length]. *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! Returns @expr{1@} on success, and @expr{0@} (zero) on failure.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @seealso *! @[open()] */
cdf56e1999-05-19Mirar (Pontus Hagland) static void file_truncate(INT32 args) {
99e4f02004-10-15Henrik Grubbström (Grubba)  INT64 len = 0;
cdf56e1999-05-19Mirar (Pontus Hagland)  int res;
06bd612016-01-26Martin Nilsson  if(args!=1) SIMPLE_WRONG_NUM_ARGS_ERROR("truncate", 1);
f202eb2003-03-28Martin Stjernholm  #if defined (HAVE_FTRUNCATE64) || SIZEOF_OFF_T > SIZEOF_INT_TYPE if(is_bignum_object_in_svalue(&Pike_sp[-args])) { if (!int64_from_bignum(&len, Pike_sp[-args].u.object)) Pike_error ("Bad argument 1 to Stdio.File->truncate(). Length too large.\n"); } else #endif
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("truncate", 1, "int");
f202eb2003-03-28Martin Stjernholm  else len = Pike_sp[-args].u.integer;
cdf56e1999-05-19Mirar (Pontus Hagland)  if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
cdf56e1999-05-19Mirar (Pontus Hagland)  ERRNO=0;
f202eb2003-03-28Martin Stjernholm #ifdef HAVE_FTRUNCATE64 res = ftruncate64 (FD, len); #else
cdf56e1999-05-19Mirar (Pontus Hagland)  res=fd_ftruncate(FD, len);
f202eb2003-03-28Martin Stjernholm #endif
cdf56e1999-05-19Mirar (Pontus Hagland)  pop_n_elems(args);
ee71702000-01-30Per Hedbor  if(res<0)
cdf56e1999-05-19Mirar (Pontus Hagland)  ERRNO=errno; push_int(!res); }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl Stat stat() *! *! Get status for an open file. *!
5601732004-11-30Martin Stjernholm  *! This function returns the same information as the function *! @[file_stat()], but for the file it is called in. If file is not *! an open file, @expr{0@} (zero) is returned. Zero is also returned *! if file is a pipe or socket.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @returns *! See @[file_stat()] for a description of the return value. *! *! @seealso
0d816f2008-02-24Henrik Grubbström (Grubba)  *! @[file_stat()], @[statat()]
9c052f2001-02-15Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_stat(INT32 args) {
07513e1996-10-04Fredrik Hübinette (Hubbe)  int fd;
40962a2003-03-27Martin Stjernholm  PIKE_STAT_T s;
07513e1996-10-04Fredrik Hübinette (Hubbe)  int tmp;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
ee71702000-01-30Per Hedbor 
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
07513e1996-10-04Fredrik Hübinette (Hubbe)  fd=FD;
d3ef711995-11-02Fredrik Hübinette (Hubbe)  retry:
07513e1996-10-04Fredrik Hübinette (Hubbe)  THREADS_ALLOW();
5740881998-01-01Fredrik Hübinette (Hubbe)  tmp=fd_fstat(fd, &s);
07513e1996-10-04Fredrik Hübinette (Hubbe)  THREADS_DISALLOW(); if(tmp < 0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
00f1d92000-04-14Henrik Grubbström (Grubba)  if(errno == EINTR) { check_threads_etc(); goto retry; }
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=errno;
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_int(0); }else{
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
61a4242000-08-27Mirar (Pontus Hagland)  push_stat(&s);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
0d816f2008-02-24Henrik Grubbström (Grubba)  #ifdef HAVE_FSTATAT /*! @decl Stat statat(string path, void|int(0..1) symlink) *! *! Get status for a file relative an open directory. *! *! This function returns the same information as the function *! @[file_stat()], but relative to the file it is called in. If file is not *! an open file, @expr{0@} (zero) is returned. Zero is also returned *! if file is a pipe or socket. *! *! @returns *! See @[file_stat()] for a description of the return value. *! *! @note
e1aec82014-11-15Stephen R. van den Berg  *! Not available on all architectures.
0d816f2008-02-24Henrik Grubbström (Grubba)  *! *! @seealso
18a5112008-03-14Henrik Grubbström (Grubba)  *! @[file_stat()], @[stat()], @[openat()], @[unlinkat()]
0d816f2008-02-24Henrik Grubbström (Grubba)  */ static void file_statat(INT32 args) { int fd; PIKE_STAT_T s; int tmp; struct pike_string *path; int nofollow = 0; if(FD < 0) Pike_error("File not open.\n"); get_all_args("statat", args, "%S.%d", &path, &nofollow); if (string_has_null(path)) { /* Filenames with NUL are not supported. */ ERRNO = errno = ENOENT; pop_n_elems(args); push_int(0); return; } fd=FD; retry: THREADS_ALLOW();
16062a2008-02-24Henrik Grubbström (Grubba)  tmp = fstatat(fd, path->str, &s, nofollow?AT_SYMLINK_NOFOLLOW:0);
0d816f2008-02-24Henrik Grubbström (Grubba)  THREADS_DISALLOW(); if(tmp < 0) { if(errno == EINTR) { check_threads_etc(); goto retry; } ERRNO=errno; push_int(0); }else{ ERRNO=0; push_stat(&s); } stack_pop_n_elems_keep_top(args); }
18a5112008-03-14Henrik Grubbström (Grubba)  #ifdef HAVE_UNLINKAT /*! @decl int unlinkat(string f) *! *! Remove a file or directory relative to an open file. *! *! @returns *! Returns @expr{0@} (zero) on failure, @expr{1@} otherwise. *! *! @seealso *! @[rm()], @[openat()], @[statat()] */ static void file_unlinkat(INT32 args) { int dir_fd; PIKE_STAT_T st; struct pike_string *str; INT32 i; destruct_objects_to_destruct(); if((dir_fd = FD) < 0) Pike_error("File not open.\n"); get_all_args("unlinkat", args, "%S", &str); if (string_has_null(str)) { /* Filenames with NUL are not supported. */ ERRNO = ENOENT; pop_n_elems(args); push_int(0); return; } THREADS_ALLOW_UID(); do { i = fstatat(dir_fd, str->str, &st, AT_SYMLINK_NOFOLLOW); } while ((i < 0) && (errno == EINTR)); if (i >= 0) { int flag = 0; if ((st.st_mode & S_IFMT) == S_IFDIR) { flag = AT_REMOVEDIR; } do { i = unlinkat(dir_fd, str->str, flag); } while ((i < 0) && (errno == EINTR)); } THREADS_DISALLOW_UID(); pop_n_elems(args); if (i < 0) { ERRNO = errno; push_int(0); } else { push_int(1); } } #endif /* HAVE_UNLINKAT */
0d816f2008-02-24Henrik Grubbström (Grubba) #endif /* HAVE_FSTATAT */
71c0062014-03-03Henrik Grubbström (Grubba) #if defined(HAVE_FDOPENDIR) && defined(HAVE_OPENAT) /*! @decl array(string) get_dir(string|void path) *! *! Get directory contents relative to an open directory. *! *! @param path *! Path relative to the open directory. Defaults to the *! directory itself. *! *! @returns *! Returns an array of filenames. *! *! @note
e1aec82014-11-15Stephen R. van den Berg  *! Not available on all architectures.
71c0062014-03-03Henrik Grubbström (Grubba)  *! *! @seealso *! @[predef::get_dir()], @[statat()], @[openat()], @[unlinkat()] */ static void file_get_dir(INT32 args) { int fd; int dfd; struct pike_string *path = NULL; ptrdiff_t name_max = -1; DIR *dir = NULL; if(FD < 0) Pike_error("File not open.\n"); get_all_args("get_dir", args, ".%S", &path); if (path && string_has_null(path)) { fprintf(stderr, "NULL\n"); /* Filenames with NUL are not supported. */ ERRNO = errno = ENOENT; pop_n_elems(args); push_int(0); return; } fd = FD; dfd = -1; while(1) { THREADS_ALLOW_UID(); if (!path) { dfd = dup(fd); } else { dfd = openat(fd, path->str, O_RDONLY); } THREADS_DISALLOW_UID(); if ((dfd == -1) && (errno == EINTR)) { check_threads_etc(); continue; } break; } if (dfd == -1) { ERRNO = errno; pop_n_elems(args); push_int(0); return; } #ifdef HAVE_FPATHCONF name_max = fpathconf(dfd, _PC_NAME_MAX); #endif /* HAVE_FPATHCONF */ if (!(dir = fdopendir(dfd))) { ERRNO = errno; close(dfd); pop_n_elems(args); push_int(0); return; } /* NB: The fd dfd has been eaten by fdopendir(3), * so we don't need to close it. */ low_get_dir(dir, name_max); } #endif /* HAVE_FDOPENDIR && HAVE_OPENAT */
3c44292005-04-29Per Hedbor #if defined(HAVE_FSETXATTR) && defined(HAVE_FGETXATTR) && defined(HAVE_FLISTXATTR) /* All A-OK.*/ /*! @decl array(string) listxattr( )
13670c2015-05-25Martin Nilsson  *!
3c44292005-04-29Per Hedbor  *! Return an array of all extended attributes set on the file */ static void file_listxattr(INT32 args) { char buffer[1024]; char *ptr = buffer; int mfd = FD, do_free = 0; ssize_t res; pop_n_elems( args ); THREADS_ALLOW(); do {
c8bbef2005-05-31H. William Welliver III #ifdef HAVE_DARWIN_XATTR res = flistxattr( mfd, buffer, sizeof(buffer), 0 ); /* First try, for speed.*/ #else
3c44292005-04-29Per Hedbor  res = flistxattr( mfd, buffer, sizeof(buffer) ); /* First try, for speed.*/
c8bbef2005-05-31H. William Welliver III #endif /* HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor  } while( res < 0 && errno == EINTR ); THREADS_DISALLOW(); if( res<0 && errno==ERANGE ) { /* Too little space in buffer.*/
4107532010-02-23Stephen R. van den Berg  int blen = DIRECT_BUFSIZE;
136bf82005-04-29Henrik Grubbström (Grubba)  do_free = 1;
3c44292005-04-29Per Hedbor  ptr = xalloc( 1 ); do {
136bf82005-04-29Henrik Grubbström (Grubba)  char *tmp = realloc( ptr, blen );
3c44292005-04-29Per Hedbor  if( !tmp ) break; ptr = tmp; THREADS_ALLOW(); do {
c8bbef2005-05-31H. William Welliver III #ifdef HAVE_DARWIN_XATTR res = flistxattr( mfd, ptr, blen, 0 ); #else
136bf82005-04-29Henrik Grubbström (Grubba)  res = flistxattr( mfd, ptr, blen );
c8bbef2005-05-31H. William Welliver III #endif /* HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor  } while( res < 0 && errno == EINTR ); THREADS_DISALLOW(); blen *= 2; } while( (res < 0) && (errno == ERANGE) ); } if( res < 0 ) {
aa76b42009-08-11Henrik Grubbström (Grubba)  if( do_free )
3c44292005-04-29Per Hedbor  free(ptr); push_int(0); ERRNO=errno; return; } push_string( make_shared_binary_string( ptr, res ) ); ptr[0]=0; push_string( make_shared_binary_string( ptr, 1 ) ); o_divide();
7863d62005-05-06Martin Nilsson  push_empty_string();
3c44292005-04-29Per Hedbor  f_aggregate(1); o_subtract();
13670c2015-05-25Martin Nilsson  if( do_free )
3c44292005-04-29Per Hedbor  free( ptr ); } /*! @decl string getxattr(string attr)
13670c2015-05-25Martin Nilsson  *!
3c44292005-04-29Per Hedbor  *! Return the value of a specified attribute, or 0 if it does not exist */ static void file_getxattr(INT32 args) { char buffer[1024]; char *ptr = buffer; int mfd = FD, do_free = 0; ssize_t res; char *name;
13670c2015-05-25Martin Nilsson 
3c44292005-04-29Per Hedbor  get_all_args( "getxattr", args, "%s", &name ); THREADS_ALLOW(); do {
c8bbef2005-05-31H. William Welliver III #ifdef HAVE_DARWIN_XATTR res = fgetxattr( mfd, name, buffer, sizeof(buffer), 0, 0 ); /* First try, for speed.*/ #else
3c44292005-04-29Per Hedbor  res = fgetxattr( mfd, name, buffer, sizeof(buffer) ); /* First try, for speed.*/
c8bbef2005-05-31H. William Welliver III #endif /* HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor  } while( res < 0 && errno == EINTR ); THREADS_DISALLOW(); if( res<0 && errno==ERANGE ) { /* Too little space in buffer.*/
4107532010-02-23Stephen R. van den Berg  int blen = DIRECT_BUFSIZE;
136bf82005-04-29Henrik Grubbström (Grubba)  do_free = 1;
3c44292005-04-29Per Hedbor  ptr = xalloc( 1 ); do {
136bf82005-04-29Henrik Grubbström (Grubba)  char *tmp = realloc( ptr, blen );
3c44292005-04-29Per Hedbor  if( !tmp ) break; ptr = tmp; THREADS_ALLOW(); do {
c8bbef2005-05-31H. William Welliver III #ifdef HAVE_DARWIN_XATTR res = fgetxattr( mfd, name, ptr, blen, 0, 0 ); #else
136bf82005-04-29Henrik Grubbström (Grubba)  res = fgetxattr( mfd, name, ptr, blen );
c8bbef2005-05-31H. William Welliver III #endif /* HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor  } while( res < 0 && errno == EINTR ); THREADS_DISALLOW(); blen *= 2; } while( (res < 0) && (errno == ERANGE) ); } if( res < 0 ) { if( do_free && ptr ) free(ptr); push_int(0); ERRNO=errno; return; } push_string( make_shared_binary_string( ptr, res ) );
13670c2015-05-25Martin Nilsson  if( do_free && ptr )
3c44292005-04-29Per Hedbor  free( ptr ); } /*! @decl void removexattr( string attr ) *! Remove the specified extended attribute. */ static void file_removexattr( INT32 args ) { char *name; int mfd = FD; int rv; get_all_args( "removexattr", args, "%s", &name ); THREADS_ALLOW();
c8bbef2005-05-31H. William Welliver III #ifdef HAVE_DARWIN_XATTR while( ((rv=fremovexattr( mfd, name, 0 )) < 0) && (errno == EINTR)) ; #else
136bf82005-04-29Henrik Grubbström (Grubba)  while( ((rv=fremovexattr( mfd, name )) < 0) && (errno == EINTR)) ;
c8bbef2005-05-31H. William Welliver III #endif /* HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor  THREADS_DISALLOW(); pop_n_elems(args); if( rv < 0 ) { ERRNO=errno; push_int(0); } else { push_int(1); } } /*! @decl void setxattr( string attr, string value, int flags) *! *! Set the attribute @[attr] to the value @[value]. *!
13670c2015-05-25Martin Nilsson  *! The flags parameter can be used to refine the semantics of the operation.
3c44292005-04-29Per Hedbor  *!
7e8cb42007-03-04Martin Nilsson  *! @[Stdio.XATTR_CREATE] specifies a pure create, which
13670c2015-05-25Martin Nilsson  *! fails if the named attribute exists already.
3c44292005-04-29Per Hedbor  *!
7e8cb42007-03-04Martin Nilsson  *! @[Stdio.XATTR_REPLACE] specifies a pure replace operation, which *! fails if the named attribute does not already exist.
3c44292005-04-29Per Hedbor  *!
13670c2015-05-25Martin Nilsson  *! By default (no flags), the extended attribute will be created if need be,
3c44292005-04-29Per Hedbor  *! or will simply replace the value if the attribute exists. *! *! @returns *! 1 if successful, 0 otherwise, setting errno. */ static void file_setxattr( INT32 args ) { char *ind; struct pike_string *val; int flags; int rv; int mfd = FD; get_all_args( "setxattr", args, "%s%S%d", &ind, &val, &flags ); THREADS_ALLOW();
c8bbef2005-05-31H. William Welliver III #ifdef HAVE_DARWIN_XATTR while( ((rv=fsetxattr( mfd, ind, val->str, (val->len<<val->size_shift), 0, flags )) < 0) && (errno == EINTR)) ; #else
136bf82005-04-29Henrik Grubbström (Grubba)  while( ((rv=fsetxattr( mfd, ind, val->str, (val->len<<val->size_shift), flags )) < 0) && (errno == EINTR)) ;
c8bbef2005-05-31H. William Welliver III #endif /* HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor  THREADS_DISALLOW(); pop_n_elems(args); if( rv < 0 ) { ERRNO=errno; push_int(0); } else push_int(1); } #endif
1053be2001-11-22Martin Nilsson /*! @decl int errno() *! *! Return the errno for the latest failed file operation.
9c052f2001-02-15Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_errno(INT32 args) { pop_n_elems(args);
06983f1996-09-22Fredrik Hübinette (Hubbe)  push_int(ERRNO);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
29d1c02016-08-05Henrik Grubbström (Grubba) /*! @decl FileModeFlags|FilePropertyFlags mode()
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
2877952009-06-10Henrik Grubbström (Grubba)  *! Returns the open mode and capabilities for the file.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
2877952009-06-10Henrik Grubbström (Grubba)  *! @returns *! Returns an @[`|()] of the following flags:
04538b2003-03-03Martin Nilsson  *! @int *! @value 0x1000
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[FILE_READ]
04538b2003-03-03Martin Nilsson  *! @value 0x2000
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[FILE_WRITE]
04538b2003-03-03Martin Nilsson  *! @value 0x4000
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[FILE_APPEND]
04538b2003-03-03Martin Nilsson  *! @value 0x8000
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[FILE_CREATE]
04538b2003-03-03Martin Nilsson  *! @value 0x0100
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[FILE_TRUNC]
04538b2003-03-03Martin Nilsson  *! @value 0x0200
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[FILE_EXCLUSIVE]
04538b2003-03-03Martin Nilsson  *! @value 0x0400
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[FILE_NONBLOCKING]
2877952009-06-10Henrik Grubbström (Grubba)  *! @value 0x0040
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[PROP_SEND_FD]
2877952009-06-10Henrik Grubbström (Grubba)  *! @value 0x0010
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[PROP_BIDIRECTIONAL]
2877952009-06-10Henrik Grubbström (Grubba)  *! @value 0x0008
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[PROP_BUFFERED]
2877952009-06-10Henrik Grubbström (Grubba)  *! @value 0x0004
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[PROP_SHUTDOWN]
2877952009-06-10Henrik Grubbström (Grubba)  *! @value 0x0002
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[PROP_NONBLOCK]
2877952009-06-10Henrik Grubbström (Grubba)  *! @value 0x0001
db6ee82009-06-10Henrik Grubbström (Grubba)  *! @[PROP_IPC]
04538b2003-03-03Martin Nilsson  *! @endint *!
2877952009-06-10Henrik Grubbström (Grubba)  *! @note
e1aec82014-11-15Stephen R. van den Berg  *! In some versions of Pike 7.8 the @tt{PROP_@} flags were
2877952009-06-10Henrik Grubbström (Grubba)  *! filtered from the result. *!
9c052f2001-02-15Henrik Grubbström (Grubba)  *! @seealso *! @[open()] */
83226a1999-04-19Henrik Grubbström (Grubba) static void file_mode(INT32 args) { pop_n_elems(args);
2877952009-06-10Henrik Grubbström (Grubba)  push_int(THIS->open_mode);
83226a1999-04-19Henrik Grubbström (Grubba) }
7e63662003-10-24Martin Stjernholm /*! @decl void set_backend (Pike.Backend backend) *! *! Set the backend used for the callbacks. *! *! @note
10dac82004-04-05Martin Stjernholm  *! The backend keeps a reference to this object only when it is in *! callback mode. So if this object hasn't got any active callbacks *! and it runs out of other references, it will still be destructed *! quickly (after closing, if necessary). *! *! Also, this object does not keep a reference to the backend.
7e63662003-10-24Martin Stjernholm  *! *! @seealso
ca6bd02012-05-01Bill Welliver  *! @[query_backend], @[set_nonblocking], @[set_read_callback], @[set_write_callback], @[set_fs_event_callback]
7e63662003-10-24Martin Stjernholm  */ static void file_set_backend (INT32 args) {
10dac82004-04-05Martin Stjernholm  struct my_file *f = THIS;
7e63662003-10-24Martin Stjernholm  struct Backend_struct *backend;
06bd612016-01-26Martin Nilsson  if (args!=1) SIMPLE_WRONG_NUM_ARGS_ERROR ("set_backend", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-args]) != PIKE_T_OBJECT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR ("set_backend", 1, "Pike.Backend");
13b5ed2014-05-26Per Hedbor  backend = get_storage (Pike_sp[-args].u.object, Backend_program);
7e63662003-10-24Martin Stjernholm  if (!backend)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR ("set_backend", 1, "Pike.Backend");
7e63662003-10-24Martin Stjernholm 
2c03b42008-01-27Henrik Grubbström (Grubba)  /* FIXME: Only allow set_backend() if the file is open? */
d156802008-01-01Henrik Grubbström (Grubba) #ifdef __NT__
2c03b42008-01-27Henrik Grubbström (Grubba)  if ((THIS->box.fd >= 0) && !(fd_query_properties(THIS->box.fd, fd_CAN_NONBLOCK) & fd_CAN_NONBLOCK)) {
d156802008-01-01Henrik Grubbström (Grubba)  Pike_error("set_backend() on non-socket!\n"); } #endif /* __NT__ */
10dac82004-04-05Martin Stjernholm  if (f->box.backend) change_backend_for_box (&f->box, backend); else INIT_FD_CALLBACK_BOX (&f->box, backend, f->box.ref_obj,
ca6bd02012-05-01Bill Welliver  f->box.fd, 0, got_fd_event, f->box.flags);
7e63662003-10-24Martin Stjernholm } /*! @decl Pike.Backend query_backend() *! *! Return the backend used for the callbacks. *! *! @seealso *! @[set_backend] */ static void file_query_backend (INT32 args) { pop_n_elems (args);
10dac82004-04-05Martin Stjernholm  ref_push_object (get_backend_obj (THIS->box.backend ? THIS->box.backend : default_backend));
7e63662003-10-24Martin Stjernholm }
1053be2001-11-22Martin Nilsson /*! @decl void set_nonblocking() *! *! Sets this file to nonblocking operation. *!
5729522003-10-06Henrik Grubbström (Grubba)  *! @note *! Nonblocking operation is not supported on all Stdio.File objects. *! Notably it is not guaranteed to be supported on objects returned *! by @[pipe()] unless @[PROP_NONBLOCK] was specified in the call *! to @[pipe()]. *!
1053be2001-11-22Martin Nilsson  *! @seealso *! @[set_blocking()]
9c052f2001-02-15Henrik Grubbström (Grubba)  */
96f63c2015-11-25Henrik Grubbström (Grubba) static void file_set_nonblocking(INT32 UNUSED(args))
2b10c61996-12-03Fredrik Hübinette (Hubbe) {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  if(FD < 0) Pike_error("File not open.\n");
2b10c61996-12-03Fredrik Hübinette (Hubbe) 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(!(THIS->open_mode & fd_CAN_NONBLOCK))
a3ead52003-10-24Martin Stjernholm  Pike_error("This file does not support nonblocking operation.\n");
bcf9461998-01-27Fredrik Hübinette (Hubbe) 
a0a9371998-02-10Fredrik Hübinette (Hubbe)  if(set_nonblocking(FD,1)) { ERRNO=errno;
a3ead52003-10-24Martin Stjernholm  push_int (ERRNO); f_strerror (1);
9606eb2004-11-12Henrik Grubbström (Grubba)  Pike_error("Stdio.File->set_nonblocking() failed: %S\n", Pike_sp[-1].u.string);
a0a9371998-02-10Fredrik Hübinette (Hubbe)  }
c657d01997-01-29Fredrik Hübinette (Hubbe)  THIS->open_mode |= FILE_NONBLOCKING;
9c052f2001-02-15Henrik Grubbström (Grubba) }
2b10c61996-12-03Fredrik Hübinette (Hubbe) 
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl void set_blocking() *! *! Sets this file to blocking operation. *! *! This is the inverse operation of @[set_nonblocking()]. *! *! @seealso *! @[set_nonblocking()] */
96f63c2015-11-25Henrik Grubbström (Grubba) static void file_set_blocking(INT32 UNUSED(args))
5267b71995-08-09Fredrik Hübinette (Hubbe) {
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD >= 0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  set_nonblocking(FD,0);
c657d01997-01-29Fredrik Hübinette (Hubbe)  THIS->open_mode &=~ FILE_NONBLOCKING;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl void set_close_on_exec(int(0..1) yes_no) *! *! Marks the file as to be closed in spawned processes. *! *! This function determines whether this file will be closed when *! calling exec(). *! *! Default is that the file WILL be closed on exec except for *! stdin, stdout and stderr. *! *! @seealso *! @[Process.create_process()], @[exec()] */
f6f02d1995-10-16Fredrik Hübinette (Hubbe) static void file_set_close_on_exec(INT32 args) {
06bd612016-01-26Martin Nilsson  if(args != 1) SIMPLE_WRONG_NUM_ARGS_ERROR("set_close_on_exec", 1);
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD <0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
f6f02d1995-10-16Fredrik Hübinette (Hubbe) 
9f516a2001-12-16Martin Stjernholm  if(UNSAFE_IS_ZERO(Pike_sp-args))
f6f02d1995-10-16Fredrik Hübinette (Hubbe)  {
c657d01997-01-29Fredrik Hübinette (Hubbe)  my_set_close_on_exec(FD,0);
f6f02d1995-10-16Fredrik Hübinette (Hubbe)  }else{
c657d01997-01-29Fredrik Hübinette (Hubbe)  my_set_close_on_exec(FD,1);
f6f02d1995-10-16Fredrik Hübinette (Hubbe)  } }
2c65362004-04-05Martin Stjernholm /*! @decl int is_open() *! *! Returns true if the file is open. *! *! @note
e565022004-11-30Martin Stjernholm  *! If the file is a socket that has been closed from the remote side, *! this function might still return true. *! *! @note
2c65362004-04-05Martin Stjernholm  *! Most methods can't be called for a file descriptor that isn't *! open. Notable exceptions @[errno], @[mode], and the set and query *! functions for callbacks and backend. */ static void file_is_open (INT32 args) {
e565022004-11-30Martin Stjernholm  /* Note: Even though we'd like to, we can't accurately tell whether * a socket has been closed from the remote end or not. */
2c65362004-04-05Martin Stjernholm  pop_n_elems (args); push_int (FD >= 0); }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int query_fd() *! *! Returns the file descriptor number associated with this object. */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_query_fd(INT32 args) {
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
f0d73c1995-11-04Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  push_int(FD);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
4945cb2004-07-02Stephen R. van den Berg /*! @decl int release_fd() *!
9b40702004-07-02Martin Stjernholm  *! Returns the file descriptor number associated with this object, in *! addition to releasing it so that this object behaves as if closed. *! Other settings like callbacks and backend remain intact. *! @[take_fd] can later be used to reinstate the file descriptor so *! that the state is restored. *!
4945cb2004-07-02Stephen R. van den Berg  *! @seealso *! @[query_fd()], @[take_fd()] */ static void file_release_fd(INT32 args) { file_query_fd(args); change_fd_for_box(&THIS->box, -1); } /*! @decl void take_fd(int fd) *!
9b40702004-07-02Martin Stjernholm  *! Rehooks the given file descriptor number to be associated with *! this object. As opposed to using @[open] with a file descriptor *! number, it will be closed by this object upon destruct or when *! @[close] is called. *!
4945cb2004-07-02Stephen R. van den Berg  *! @seealso *! @[release_fd()] */ static void file_take_fd(INT32 args) {
06bd612016-01-26Martin Nilsson  if (args != 1) SIMPLE_WRONG_NUM_ARGS_ERROR ("take_fd", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR ("take_fd", 0, "int");
4945cb2004-07-02Stephen R. van den Berg  change_fd_for_box(&THIS->box, Pike_sp[-args].u.integer); }
097de92006-07-05Martin Stjernholm PMOD_EXPORT struct object *file_make_object_from_fd(int fd, int mode, int guess)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
6bae0c2009-02-22Henrik Grubbström (Grubba)  struct object *o; struct my_file *f; if (Pike_fp->context->prog == file_program) { /* Called from within the file (aka Fd) object. * Attempt to clone ourselves. */ ONERROR err;
9a7ce92009-03-12Martin Stjernholm  SET_ONERROR(err, do_close_fd, (ptrdiff_t) fd);
6bae0c2009-02-22Henrik Grubbström (Grubba)  o = clone_object_from_object(Pike_fp->current_object, 0); UNSET_ONERROR(err); if (!o->prog) return NULL; /* Destructed in create() or __INIT(). */ f = (struct my_file *)(o->storage + Pike_fp->context->storage_offset);
f126b62010-11-19Henrik Grubbström (Grubba)  f->flags |= (THIS->flags & FILE_HAVE_RECV_FD);
6bae0c2009-02-22Henrik Grubbström (Grubba)  } else { /* Clone a plain Fd object. */ o = low_clone(file_program);
292cfe2009-02-24Henrik Grubbström (Grubba)  f = (struct my_file *) o->storage + file_program->inherits->storage_offset;
6bae0c2009-02-22Henrik Grubbström (Grubba)  call_c_initializers(o); }
60208c2008-06-12Henrik Grubbström (Grubba)  change_fd_for_box(&f->box, fd);
8317a52004-04-06Henrik Grubbström (Grubba)  if (fd >= 0) { f->open_mode=mode | fd_query_properties(fd, guess);
a0590e2003-10-28Martin Stjernholm #ifdef PIKE_DEBUG
8317a52004-04-06Henrik Grubbström (Grubba)  debug_check_fd_not_in_use (fd);
a0590e2003-10-28Martin Stjernholm #endif
8317a52004-04-06Henrik Grubbström (Grubba)  } else { f->open_mode = 0; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  return o; }
da7e5d2009-02-23Henrik Grubbström (Grubba) PMOD_EXPORT void push_new_fd_object(int factory_fun_num, int fd, int mode, int guess) { struct object *o = NULL; struct my_file *f; ONERROR err;
f126b62010-11-19Henrik Grubbström (Grubba)  struct inherit *inh; struct identifier *i;
da7e5d2009-02-23Henrik Grubbström (Grubba) 
9a7ce92009-03-12Martin Stjernholm  SET_ONERROR(err, do_close_fd, (ptrdiff_t) fd);
da7e5d2009-02-23Henrik Grubbström (Grubba)  apply_current(factory_fun_num, 0);
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(Pike_sp[-1]) != PIKE_T_OBJECT) ||
da7e5d2009-02-23Henrik Grubbström (Grubba)  !(o = Pike_sp[-1].u.object)->prog ||
017b572011-10-28Henrik Grubbström (Grubba)  ((inh = &o->prog->inherits[SUBTYPEOF(Pike_sp[-1])])->prog != file_program)) {
da7e5d2009-02-23Henrik Grubbström (Grubba)  Pike_error("Invalid return value from fd_factory(). " "Expected object(is Stdio.Fd).\n"); }
f126b62010-11-19Henrik Grubbström (Grubba)  f = (struct my_file *)(o->storage + inh->storage_offset);
da7e5d2009-02-23Henrik Grubbström (Grubba)  if (f->box.fd != -1) { Pike_error("Invalid return value from fd_factory(). "
292cfe2009-02-24Henrik Grubbström (Grubba)  "Expected unopened object(is Stdio.Fd). fd:%d\n", f->box.fd);
da7e5d2009-02-23Henrik Grubbström (Grubba)  } UNSET_ONERROR(err); change_fd_for_box(&f->box, fd); if (fd >= 0) { f->open_mode=mode | fd_query_properties(fd, guess); #ifdef PIKE_DEBUG debug_check_fd_not_in_use (fd); #endif } else { f->open_mode = 0; }
f126b62010-11-19Henrik Grubbström (Grubba)  i = ID_FROM_INT(o->prog, fd_receive_fd_fun_num + inh->identifier_level); if (((i->identifier_flags & IDENTIFIER_TYPE_MASK) == IDENTIFIER_PIKE_FUNCTION) && (i->func.offset != -1)) { /* receive_fd() is not a prototype. */ f->flags |= FILE_HAVE_RECV_FD; }
da7e5d2009-02-23Henrik Grubbström (Grubba) }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl void set_buffer(int bufsize, string mode) *! @decl void set_buffer(int bufsize) *! *! Set internal socket buffer. *! *! This function sets the internal buffer size of a socket or stream. *! *! The second argument allows you to set the read or write buffer by
cbe8c92003-04-07Martin Nilsson  *! specifying @expr{"r"@} or @expr{"w"@}.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @note *! It is not guaranteed that this function actually does anything, *! but it certainly helps to increase data transfer speed when it does. *! *! @seealso *! @[open_socket()], @[accept()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_set_buffer(INT32 args) { INT32 bufsize; int flags;
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD==-1)
b1c4582003-01-11Martin Nilsson  Pike_error("Stdio.File->set_buffer() on closed file.\n");
3551c02016-02-24Henrik Grubbström (Grubba)  if(args<1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("set_buffer", 1);
3551c02016-02-24Henrik Grubbström (Grubba)  if(args>2) SIMPLE_WRONG_NUM_ARGS_ERROR("set_buffer", 2);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("set_buffer", 1, "int");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5923b12000-07-06Fredrik Hübinette (Hubbe)  bufsize=Pike_sp[-args].u.integer;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(bufsize < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bufsize must be larger than zero.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(args>1) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[1-args]) != PIKE_T_STRING)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("set_buffer", 2, "string");
5923b12000-07-06Fredrik Hübinette (Hubbe)  flags=parse(Pike_sp[1-args].u.string->str);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ flags=FILE_READ | FILE_WRITE; } #ifdef SOCKET_BUFFER_MAX #if SOCKET_BUFFER_MAX if(bufsize>SOCKET_BUFFER_MAX) bufsize=SOCKET_BUFFER_MAX; #endif
a1ef721998-04-05Fredrik Hübinette (Hubbe)  flags &= THIS->open_mode;
439e0f1998-05-22Henrik Grubbström (Grubba) #ifdef SO_RCVBUF
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(flags & FILE_READ) { int tmp=bufsize;
5740881998-01-01Fredrik Hübinette (Hubbe)  fd_setsockopt(FD,SOL_SOCKET, SO_RCVBUF, (char *)&tmp, sizeof(tmp));
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
439e0f1998-05-22Henrik Grubbström (Grubba) #endif /* SO_RCVBUF */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
439e0f1998-05-22Henrik Grubbström (Grubba) #ifdef SO_SNDBUF
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(flags & FILE_WRITE) { int tmp=bufsize;
5740881998-01-01Fredrik Hübinette (Hubbe)  fd_setsockopt(FD,SOL_SOCKET, SO_SNDBUF, (char *)&tmp, sizeof(tmp));
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
439e0f1998-05-22Henrik Grubbström (Grubba) #endif /* SO_SNDBUF */
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif }
22ef232010-02-18Henrik Grubbström (Grubba) #if !defined(HAVE_SOCKETPAIR) || !defined(UNIX_SOCKETS_WORKS_WITH_SHUTDOWN)
1d16fe2010-02-18Henrik Grubbström (Grubba)  /* Paranoia... */
22ef232010-02-18Henrik Grubbström (Grubba) #undef UNIX_SOCKETS_WORKS_WITH_SHUTDOWN
1d16fe2010-02-18Henrik Grubbström (Grubba) 
e353071998-05-22Henrik Grubbström (Grubba) #ifndef AF_UNIX #define AF_UNIX 4711 #endif /* AF_UNIX */
0879262000-10-08Henrik Grubbström (Grubba) #ifdef SOCKETPAIR_DEBUG #define SP_DEBUG(X) fprintf X #else /* !SOCKETPAIR_DEBUG */ #define SP_DEBUG(X) #endif /* SOCKETPAIR_DEBUG */
cb22561995-10-11Fredrik Hübinette (Hubbe)  /* No socketpair() ? * No AF_UNIX sockets ? * No hope ? *
9204121997-09-07Henrik Grubbström (Grubba)  * Don't despair, socketpair_ultra is here! * Tests done by an independant institute in Europe show that
cb22561995-10-11Fredrik Hübinette (Hubbe)  * socketpair_ultra is 50% more portable than other leading * brands of socketpair. * /Hubbe */ /* redefine socketpair to something that hopefully won't * collide with any libs or headers. Also useful when testing * this code on a system that _has_ socketpair... */
b8079b1997-10-08Henrik Grubbström (Grubba) /* Protected since errno may expand to a function call. */ #ifndef errno
cb22561995-10-11Fredrik Hübinette (Hubbe) extern int errno;
b8079b1997-10-08Henrik Grubbström (Grubba) #endif /* !errno */
ef75552010-02-18Stephen R. van den Berg 
c9d4e51999-08-10Henrik Grubbström (Grubba) static int socketpair_fd = -1;
8ff74b1997-10-16Fredrik Hübinette (Hubbe) int my_socketpair(int family, int type, int protocol, int sv[2])
cb22561995-10-11Fredrik Hübinette (Hubbe) {
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  static struct sockaddr_in my_addr;
cb22561995-10-11Fredrik Hübinette (Hubbe)  struct sockaddr_in addr,addr2;
9b75fa1998-06-27Henrik Grubbström (Grubba)  int retries=0;
c9d4e51999-08-10Henrik Grubbström (Grubba)  /* Solaris and AIX think this variable should be a size_t, everybody else
7584821998-08-06Henrik Grubbström (Grubba)  * thinks it should be an int.
f850331998-07-16Fredrik Hübinette (Hubbe)  */
7c6a531998-08-07Henrik Grubbström (Grubba)  ACCEPT_SIZE_T len;
cb22561995-10-11Fredrik Hübinette (Hubbe) 
21b12a2014-09-03Martin Nilsson  memset(&addr,0,sizeof(struct sockaddr_in));
cb22561995-10-11Fredrik Hübinette (Hubbe)  /* We lie, we actually create an AF_INET socket... */ if(family != AF_UNIX || type != SOCK_STREAM) { errno=EINVAL;
ee71702000-01-30Per Hedbor  return -1;
cb22561995-10-11Fredrik Hübinette (Hubbe)  }
2c03b42008-01-27Henrik Grubbström (Grubba)  sv[0] = -1; if((sv[1]=fd_socket(AF_INET, SOCK_STREAM, 0)) <0) { SP_DEBUG((stderr, "my_socketpair:fd_socket() failed, errno:%d (2)\n", errno)); return -1; } /* FIXME: The remainder of the code is NOT multithread-safe! */
c9d4e51999-08-10Henrik Grubbström (Grubba)  if(socketpair_fd==-1)
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  {
0879262000-10-08Henrik Grubbström (Grubba)  if((socketpair_fd=fd_socket(AF_INET, SOCK_STREAM, 0)) < 0) { SP_DEBUG((stderr, "my_socketpair:fd_socket() failed, errno:%d\n", errno));
c9d4e51999-08-10Henrik Grubbström (Grubba)  return -1;
0879262000-10-08Henrik Grubbström (Grubba)  }
ee71702000-01-30Per Hedbor 
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  /* I wonder what is most common a loopback on ip# 127.0.0.1 or * a loopback with the name "localhost"?
998bd21997-09-22Henrik Grubbström (Grubba)  * Let's hope those few people who don't have socketpair have
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  * a loopback on 127.0.0.1 */
21b12a2014-09-03Martin Nilsson  memset(&my_addr,0,sizeof(struct sockaddr_in));
5740881998-01-01Fredrik Hübinette (Hubbe)  my_addr.sin_family=AF_INET;
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  my_addr.sin_addr.s_addr=htonl(INADDR_ANY); my_addr.sin_port=htons(0);
5740881998-01-01Fredrik Hübinette (Hubbe) 
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  /* Bind our sockets on any port */
c9d4e51999-08-10Henrik Grubbström (Grubba)  if(fd_bind(socketpair_fd, (struct sockaddr *)&my_addr, sizeof(addr)) < 0)
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  {
0879262000-10-08Henrik Grubbström (Grubba)  SP_DEBUG((stderr, "my_socketpair:fd_bind() failed, errno:%d\n", errno));
ae39322003-09-30Martin Stjernholm  while (fd_close(socketpair_fd) && errno == EINTR) {}
c9d4e51999-08-10Henrik Grubbström (Grubba)  socketpair_fd=-1;
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  return -1; }
cb22561995-10-11Fredrik Hübinette (Hubbe) 
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  /* Check what ports we got.. */
634a571998-08-07Henrik Grubbström (Grubba)  len = sizeof(my_addr);
c9d4e51999-08-10Henrik Grubbström (Grubba)  if(fd_getsockname(socketpair_fd,(struct sockaddr *)&my_addr,&len) < 0)
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  {
0879262000-10-08Henrik Grubbström (Grubba)  SP_DEBUG((stderr, "my_socketpair:fd_getsockname() failed, errno:%d\n", errno));
ae39322003-09-30Martin Stjernholm  while (fd_close(socketpair_fd) && errno == EINTR) {}
c9d4e51999-08-10Henrik Grubbström (Grubba)  socketpair_fd=-1;
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  return -1; }
cb22561995-10-11Fredrik Hübinette (Hubbe) 
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  /* Listen to connections on our new socket */
c9d4e51999-08-10Henrik Grubbström (Grubba)  if(fd_listen(socketpair_fd, 5) < 0)
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  {
0879262000-10-08Henrik Grubbström (Grubba)  SP_DEBUG((stderr, "my_socketpair:fd_listen() failed, errno:%d\n", errno));
ae39322003-09-30Martin Stjernholm  while (fd_close(socketpair_fd) && errno == EINTR) {}
c9d4e51999-08-10Henrik Grubbström (Grubba)  socketpair_fd=-1;
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  return -1; }
5740881998-01-01Fredrik Hübinette (Hubbe) 
c9d4e51999-08-10Henrik Grubbström (Grubba)  set_close_on_exec(socketpair_fd, 1); set_nonblocking(socketpair_fd, 1);
bcf9461998-01-27Fredrik Hübinette (Hubbe) 
5740881998-01-01Fredrik Hübinette (Hubbe)  my_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  }
ee71702000-01-30Per Hedbor 
83a7641996-12-15Fredrik Hübinette (Hubbe) /* set_nonblocking(sv[1],1); */
5740881998-01-01Fredrik Hübinette (Hubbe) 
bcf9461998-01-27Fredrik Hübinette (Hubbe) retry_connect: retries++;
5740881998-01-01Fredrik Hübinette (Hubbe)  if(fd_connect(sv[1], (struct sockaddr *)&my_addr, sizeof(addr)) < 0)
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  {
dd990d1998-12-31Fredrik Hübinette (Hubbe) /* fprintf(stderr,"errno=%d (%d)\n",errno,EWOULDBLOCK); */
0879262000-10-08Henrik Grubbström (Grubba)  SP_DEBUG((stderr, "my_socketpair:fd_connect() failed, errno:%d (%d)\n", errno, EWOULDBLOCK));
02e2012001-06-25Henrik Grubbström (Grubba)  if((errno != EWOULDBLOCK) #ifdef WSAEWOULDBLOCK && (errno != WSAEWOULDBLOCK) #endif /* WSAEWOULDBLOCK */ )
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  {
bcf9461998-01-27Fredrik Hübinette (Hubbe)  int tmp2; for(tmp2=0;tmp2<20;tmp2++) {
634a571998-08-07Henrik Grubbström (Grubba)  int tmp;
7c6a531998-08-07Henrik Grubbström (Grubba)  ACCEPT_SIZE_T len2;
634a571998-08-07Henrik Grubbström (Grubba) 
eaf8b91998-07-15Fredrik Hübinette (Hubbe)  len2=sizeof(addr);
c9d4e51999-08-10Henrik Grubbström (Grubba)  tmp=fd_accept(socketpair_fd,(struct sockaddr *)&addr,&len2);
ee71702000-01-30Per Hedbor 
0879262000-10-08Henrik Grubbström (Grubba)  if(tmp!=-1) { SP_DEBUG((stderr, "my_socketpair:fd_accept() failed, errno:%d\n", errno));
ae39322003-09-30Martin Stjernholm  while (fd_close(tmp) && errno == EINTR) {}
0879262000-10-08Henrik Grubbström (Grubba)  }
bcf9461998-01-27Fredrik Hübinette (Hubbe)  else break; } if(retries > 20) return -1; goto retry_connect;
2bad2b1997-09-16Fredrik Hübinette (Hubbe)  } }
cb22561995-10-11Fredrik Hübinette (Hubbe) 
5740881998-01-01Fredrik Hübinette (Hubbe) 
cb22561995-10-11Fredrik Hübinette (Hubbe)  /* Accept connection * Make sure this connection was our OWN connection, * otherwise some wizeguy could interfere with our * pipe by guessing our socket and connecting at
06983f1996-09-22Fredrik Hübinette (Hubbe)  * just the right time... Pike is supposed to be
cb22561995-10-11Fredrik Hübinette (Hubbe)  * pretty safe... */ do {
7c6a531998-08-07Henrik Grubbström (Grubba)  ACCEPT_SIZE_T len3;
634a571998-08-07Henrik Grubbström (Grubba) 
2c03b42008-01-27Henrik Grubbström (Grubba)  if (sv[0] >= 0) { /* Close the bad fd from last loop. */ while (fd_close(sv[0]) && errno == EINTR) ; }
eaf8b91998-07-15Fredrik Hübinette (Hubbe)  len3=sizeof(addr);
bcf9461998-01-27Fredrik Hübinette (Hubbe)  retry_accept:
6f0f182008-04-03Per Hedbor  retries++;
cea3552013-05-30Pontus Rodling  {
e303a72013-05-30Pontus Rodling #ifdef HAVE_AND_USE_POLL struct pollfd fds; int timeout = 1;
13670c2015-05-25Martin Nilsson 
e303a72013-05-30Pontus Rodling  fds.fd = socketpair_fd; fds.events = POLLIN; fds.revents = 0; poll(&fds, 1, timeout); #else
cea3552013-05-30Pontus Rodling  fd_set fds; struct timeval tv;
e303a72013-05-30Pontus Rodling  tv.tv_usec=5;
cea3552013-05-30Pontus Rodling  tv.tv_sec=0; fd_FD_ZERO(&fds); fd_FD_SET(socketpair_fd, &fds); fd_select(socketpair_fd + 1, &fds, 0, 0, &tv);
e303a72013-05-30Pontus Rodling #endif
cea3552013-05-30Pontus Rodling  }
13670c2015-05-25Martin Nilsson 
c9d4e51999-08-10Henrik Grubbström (Grubba)  sv[0]=fd_accept(socketpair_fd,(struct sockaddr *)&addr,&len3);
7cb0171997-11-07Henrik Grubbström (Grubba)  if(sv[0] < 0) {
0879262000-10-08Henrik Grubbström (Grubba)  SP_DEBUG((stderr, "my_socketpair:fd_accept() failed, errno:%d (2)\n", errno));
6f0f182008-04-03Per Hedbor  if(retries <= 20) goto retry_accept;
ae39322003-09-30Martin Stjernholm  while (fd_close(sv[1]) && errno == EINTR) {}
7cb0171997-11-07Henrik Grubbström (Grubba)  return -1; }
83a7641996-12-15Fredrik Hübinette (Hubbe) 
503f231998-07-20Fredrik Hübinette (Hubbe)  set_nonblocking(sv[0],0);
83a7641996-12-15Fredrik Hübinette (Hubbe)  /* We do not trust accept */ len=sizeof(addr);
0879262000-10-08Henrik Grubbström (Grubba)  if(fd_getpeername(sv[0], (struct sockaddr *)&addr,&len)) { SP_DEBUG((stderr, "my_socketpair:fd_getpeername() failed, errno:%d\n", errno)); return -1; }
bcf9461998-01-27Fredrik Hübinette (Hubbe)  len=sizeof(addr);
0879262000-10-08Henrik Grubbström (Grubba)  if(fd_getsockname(sv[1],(struct sockaddr *)&addr2,&len) < 0) { SP_DEBUG((stderr, "my_socketpair:fd_getsockname() failed, errno:%d\n", errno)); return -1; }
83a7641996-12-15Fredrik Hübinette (Hubbe)  }while(len < (int)sizeof(addr) || addr2.sin_addr.s_addr != addr.sin_addr.s_addr || addr2.sin_port != addr.sin_port);
cb22561995-10-11Fredrik Hübinette (Hubbe) 
bcf9461998-01-27Fredrik Hübinette (Hubbe) /* set_nonblocking(sv[1],0); */
5740881998-01-01Fredrik Hübinette (Hubbe) 
0879262000-10-08Henrik Grubbström (Grubba)  SP_DEBUG((stderr, "my_socketpair: succeeded\n", errno));
cb22561995-10-11Fredrik Hübinette (Hubbe)  return 0; }
bcf9461998-01-27Fredrik Hübinette (Hubbe) int socketpair_ultra(int family, int type, int protocol, int sv[2])
8ff74b1997-10-16Fredrik Hübinette (Hubbe) { int retries=0; while(1) { int ret=my_socketpair(family, type, protocol, sv); if(ret>=0) return ret;
ee71702000-01-30Per Hedbor 
8ff74b1997-10-16Fredrik Hübinette (Hubbe)  switch(errno) { case EAGAIN: break; case EADDRINUSE: if(retries++ > 10) return ret; break; default: return ret; } } }
1d16fe2010-02-18Henrik Grubbström (Grubba) #ifndef HAVE_SOCKETPAIR
bcf9461998-01-27Fredrik Hübinette (Hubbe) #define socketpair socketpair_ultra
cb22561995-10-11Fredrik Hübinette (Hubbe) #endif
22ef232010-02-18Henrik Grubbström (Grubba) #endif /* !HAVE_SOCKETPAIR || !UNIX_SOCKETS_WORKS_WITH_SHUTDOWN */
cb22561995-10-11Fredrik Hübinette (Hubbe) 
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl Stdio.File pipe() *! @decl Stdio.File pipe(int flags) */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_pipe(INT32 args) {
1286c71998-07-20Henrik Grubbström (Grubba)  int inout[2] = { -1, -1 }; int i = 0;
bcf9461998-01-27Fredrik Hübinette (Hubbe)  int type=fd_CAN_NONBLOCK | fd_BIDIRECTIONAL;
9637042003-10-05Henrik Grubbström (Grubba)  int reverse;
bcf9461998-01-27Fredrik Hübinette (Hubbe)  check_all_args("file->pipe",args, BIT_INT | BIT_VOID, 0);
017b572011-10-28Henrik Grubbström (Grubba)  if(args && !SUBTYPEOF(Pike_sp[-1])) type = Pike_sp[-args].u.integer;
bcf9461998-01-27Fredrik Hübinette (Hubbe) 
9637042003-10-05Henrik Grubbström (Grubba)  reverse = type & fd_REVERSE; type &= ~fd_REVERSE;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  close_fd();
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
bcf9461998-01-27Fredrik Hübinette (Hubbe)  do { #ifdef PIPE_CAPABILITIES if(!(type & ~(PIPE_CAPABILITIES))) { i=fd_pipe(&inout[0]);
1286c71998-07-20Henrik Grubbström (Grubba)  if (i >= 0) { type=PIPE_CAPABILITIES; break; }
bcf9461998-01-27Fredrik Hübinette (Hubbe)  } #endif
22ef232010-02-18Henrik Grubbström (Grubba) #ifdef UNIX_SOCKETS_WORKS_WITH_SHUTDOWN
bcf9461998-01-27Fredrik Hübinette (Hubbe) #undef UNIX_SOCKET_CAPABILITIES
1d16fe2010-02-18Henrik Grubbström (Grubba) #define UNIX_SOCKET_CAPABILITIES (fd_INTERPROCESSABLE | fd_BIDIRECTIONAL | fd_CAN_NONBLOCK | fd_CAN_SHUTDOWN | fd_SEND_FD)
bcf9461998-01-27Fredrik Hübinette (Hubbe) #endif #if defined(HAVE_SOCKETPAIR) if(!(type & ~(UNIX_SOCKET_CAPABILITIES))) {
12c3852014-09-19Martin Nilsson  i=fd_socketpair(AF_UNIX, SOCK_STREAM, 0, inout);
1286c71998-07-20Henrik Grubbström (Grubba)  if (i >= 0) { type=UNIX_SOCKET_CAPABILITIES; break; }
bcf9461998-01-27Fredrik Hübinette (Hubbe)  } #endif
ee71702000-01-30Per Hedbor 
22ef232010-02-18Henrik Grubbström (Grubba) #ifndef UNIX_SOCKETS_WORKS_WITH_SHUTDOWN
bcf9461998-01-27Fredrik Hübinette (Hubbe)  if(!(type & ~(SOCKET_CAPABILITIES))) {
12c3852014-09-19Martin Nilsson  i=socketpair_ultra(AF_UNIX, SOCK_STREAM, 0, inout);
1286c71998-07-20Henrik Grubbström (Grubba)  if (i >= 0) { type=SOCKET_CAPABILITIES; break; } }
1d16fe2010-02-18Henrik Grubbström (Grubba) #endif
1286c71998-07-20Henrik Grubbström (Grubba)  if (!i) {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot create a pipe matching those parameters.\n");
bcf9461998-01-27Fredrik Hübinette (Hubbe)  } }while(0);
ee71702000-01-30Per Hedbor 
db3a6b1998-07-15Henrik Grubbström (Grubba)  if ((i<0) || (inout[0] < 0) || (inout[1] < 0))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
cb8c162002-12-09Henrik Grubbström (Grubba)  ERRNO=errno;
1286c71998-07-20Henrik Grubbström (Grubba)  if (inout[0] >= 0) {
ae39322003-09-30Martin Stjernholm  while (fd_close(inout[0]) && errno == EINTR) {}
1286c71998-07-20Henrik Grubbström (Grubba)  } if (inout[1] >= 0) {
ae39322003-09-30Martin Stjernholm  while (fd_close(inout[1]) && errno == EINTR) {}
db3a6b1998-07-15Henrik Grubbström (Grubba)  }
ae39322003-09-30Martin Stjernholm  errno = ERRNO;
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_int(0); }
13670c2015-05-25Martin Nilsson  else if (reverse)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
41d7dc2007-05-20Henrik Grubbström (Grubba)  init_fd(inout[1], FILE_WRITE | (type&fd_BIDIRECTIONAL?FILE_READ:0) | fd_query_properties(inout[1], type), 0);
9637042003-10-05Henrik Grubbström (Grubba)  my_set_close_on_exec(inout[1],1); my_set_close_on_exec(inout[0],1);
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&THIS->box, inout[1]);
9637042003-10-05Henrik Grubbström (Grubba)  ERRNO=0;
da7e5d2009-02-23Henrik Grubbström (Grubba)  push_new_fd_object(fd_fd_factory_fun_num, inout[0], (type&fd_BIDIRECTIONAL?FILE_WRITE:0)| FILE_READ, type);
9637042003-10-05Henrik Grubbström (Grubba)  } else {
41d7dc2007-05-20Henrik Grubbström (Grubba)  init_fd(inout[0], FILE_READ | (type&fd_BIDIRECTIONAL?FILE_WRITE:0) | fd_query_properties(inout[0], type), 0);
ee71702000-01-30Per Hedbor 
c657d01997-01-29Fredrik Hübinette (Hubbe)  my_set_close_on_exec(inout[0],1); my_set_close_on_exec(inout[1],1);
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&THIS->box, inout[0]);
ee71702000-01-30Per Hedbor 
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
da7e5d2009-02-23Henrik Grubbström (Grubba)  push_new_fd_object(fd_fd_factory_fun_num, inout[1], (type&fd_BIDIRECTIONAL?FILE_READ:0)| FILE_WRITE, type);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
b5dc812001-07-12Fredrik Hübinette (Hubbe) static void file_handle_events(int event)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
b5dc812001-07-12Fredrik Hübinette (Hubbe)  struct object *o=Pike_fp->current_object;
10dac82004-04-05Martin Stjernholm  struct my_file *f = THIS;
9ea5be2011-09-07Henrik Grubbström (Grubba)  struct identifier *i;
292cfe2009-02-24Henrik Grubbström (Grubba) 
b5dc812001-07-12Fredrik Hübinette (Hubbe)  switch(event) { case PROG_EVENT_INIT:
60208c2008-06-12Henrik Grubbström (Grubba)  f->box.backend = NULL;
41d7dc2007-05-20Henrik Grubbström (Grubba)  init_fd (-1, 0, 0);
ca6bd02012-05-01Bill Welliver  INIT_FD_CALLBACK_BOX(&f->box, NULL, o, f->box.fd, 0, got_fd_event, f->box.flags);
9ea5be2011-09-07Henrik Grubbström (Grubba)  i = ID_FROM_INT(o->prog, fd_receive_fd_fun_num + Pike_fp->context->identifier_level); if (((i->identifier_flags & IDENTIFIER_TYPE_MASK) == IDENTIFIER_PIKE_FUNCTION) && (i->func.offset != -1)) { /* receive_fd() is not a prototype. */ f->flags |= FILE_HAVE_RECV_FD; }
b5dc812001-07-12Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b5dc812001-07-12Fredrik Hübinette (Hubbe)  case PROG_EVENT_EXIT:
10dac82004-04-05Martin Stjernholm  if(!(f->flags & (FILE_NO_CLOSE_ON_DESTRUCT | FILE_LOCK_FD | FILE_NOT_OPENED)))
ba3d5c2001-09-27Fredrik Hübinette (Hubbe)  close_fd_quietly();
10dac82004-04-05Martin Stjernholm  else free_fd_stuff();
f126b62010-11-19Henrik Grubbström (Grubba) #ifdef HAVE_PIKE_SEND_FD if (f->fd_info) { free(f->fd_info); f->fd_info = NULL; } #endif
10dac82004-04-05Martin Stjernholm  unhook_fd_callback_box (&f->box);
b5dc812001-07-12Fredrik Hübinette (Hubbe)  break;
d4828c1997-07-17Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  case PROG_EVENT_GC_RECURSE: if (f->box.backend) { /* Need to deregister events if the gc has freed callbacks. * This might lead to the file object being freed altogether. */ int cb_events = 0; size_t ev; for (ev = 0; ev < NELEM (f->event_cbs); ev++)
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(f->event_cbs[ev]) != PIKE_T_INT)
10dac82004-04-05Martin Stjernholm  cb_events |= 1 << ev; SUB_FD_EVENTS (f, ~cb_events); }
b5dc812001-07-12Fredrik Hübinette (Hubbe)  break; } }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
74dfe82012-12-30Jonas Walldén static void low_dup(struct object *UNUSED(toob),
a1ef721998-04-05Fredrik Hübinette (Hubbe)  struct my_file *to, struct my_file *from)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
10dac82004-04-05Martin Stjernholm  size_t ev;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  debug_check_internals (from);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  my_set_close_on_exec(to->box.fd, to->box.fd > 2);
ee71702000-01-30Per Hedbor 
10dac82004-04-05Martin Stjernholm  to->open_mode=from->open_mode;
e9cdb42004-09-01Henrik Grubbström (Grubba)  to->flags = from->flags & ~(FILE_NO_CLOSE_ON_DESTRUCT | FILE_LOCK_FD | FILE_NOT_OPENED);
9ea5be2011-09-07Henrik Grubbström (Grubba)  /* FIXME: FILE_HAVE_RECV_FD? */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
30519a2004-09-01Henrik Grubbström (Grubba)  /* Enforce that stdin, stdout and stderr aren't closed during * normal operation. */
58125f2004-09-02Henrik Grubbström (Grubba)  if (to->box.fd <= 2) { to->flags |= FILE_NO_CLOSE_ON_DESTRUCT; dmalloc_accept_leak_fd(to->box.fd); }
30519a2004-09-01Henrik Grubbström (Grubba) 
10dac82004-04-05Martin Stjernholm  /* Note: This previously enabled all events for which there were * callbacks instead of copying the event settings from the source * file. */
ee71702000-01-30Per Hedbor 
10dac82004-04-05Martin Stjernholm  unhook_fd_callback_box (&to->box); if (from->box.backend) INIT_FD_CALLBACK_BOX (&to->box, from->box.backend, to->box.ref_obj,
ca6bd02012-05-01Bill Welliver  to->box.fd, from->box.events, got_fd_event, from->box.flags);
10dac82004-04-05Martin Stjernholm  for (ev = 0; ev < NELEM (to->event_cbs); ev++) assign_svalue (&to->event_cbs[ev], &from->event_cbs[ev]); debug_check_internals (to);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
b1c4582003-01-11Martin Nilsson /*! @decl int dup2(Stdio.File to)
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! Duplicate a file over another. *! *! This function works similarly to @[assign()], but instead of making *! the argument a reference to the same file, it creates a new file *! with the same properties and places it in the argument. *!
f830412008-06-13Henrik Grubbström (Grubba)  *! @returns *! Returns @expr{1@} on success and @expr{0@} (zero) on failure. *!
ea76b62004-08-31Henrik Grubbström (Grubba)  *! @note
e1aec82014-11-15Stephen R. van den Berg  *! @[to] need not be open, in which
5601732004-11-30Martin Stjernholm  *! case a new fd is allocated.
ea76b62004-08-31Henrik Grubbström (Grubba)  *!
f830412008-06-13Henrik Grubbström (Grubba)  *! @note *! Note also that @[to] is also assigned to the same backend (if any) *! as this object. *!
9c052f2001-02-15Henrik Grubbström (Grubba)  *! @seealso *! @[assign()], @[dup()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_dup2(INT32 args) { struct object *o;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  struct my_file *fd;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
06bd612016-01-26Martin Nilsson  if(args != 1) SIMPLE_WRONG_NUM_ARGS_ERROR("dup2", 1);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_OBJECT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("dup2", 1, "Stdio.File");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5923b12000-07-06Fredrik Hübinette (Hubbe)  o=Pike_sp[-args].u.object;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  fd=get_file_storage(o); if(!fd)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("dup2", 1, "Stdio.File");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ea76b62004-08-31Henrik Grubbström (Grubba)  if(fd->box.fd < 0) {
ab02202007-06-17Martin Stjernholm  int new_fd; if((new_fd = fd_dup(FD)) < 0)
ea76b62004-08-31Henrik Grubbström (Grubba)  { ERRNO = errno; pop_n_elems(args); push_int(0); return; }
ab02202007-06-17Martin Stjernholm  fd->box.revents = 0; change_fd_for_box (&fd->box, new_fd);
ea76b62004-08-31Henrik Grubbström (Grubba)  } else { if (fd->flags & FILE_LOCK_FD) { Pike_error("File has been temporarily locked from closing.\n"); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ea76b62004-08-31Henrik Grubbström (Grubba)  if(fd_dup2(FD, fd->box.fd) < 0) { ERRNO = errno; pop_n_elems(args); push_int(0); return; }
ab02202007-06-17Martin Stjernholm  THIS->box.revents = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  low_dup(o, fd, THIS);
ee71702000-01-30Per Hedbor 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(1); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2c65362004-04-05Martin Stjernholm /*! @decl Stdio.Fd dup()
f830412008-06-13Henrik Grubbström (Grubba)  *! *! Duplicate the file. *! *! @seealso
8b52b62008-06-13Martin Bähr  *! @[dup2()]
9c052f2001-02-15Henrik Grubbström (Grubba)  */
a1ef721998-04-05Fredrik Hübinette (Hubbe) static void file_dup(INT32 args) {
10dac82004-04-05Martin Stjernholm  int fd;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  struct object *o;
10dac82004-04-05Martin Stjernholm  struct my_file *f;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  pop_n_elems(args);
c201101998-03-25Henrik Grubbström (Grubba) 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(FD < 0)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("File not open.\n");
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  if((fd=fd_dup(FD)) < 0)
c201101998-03-25Henrik Grubbström (Grubba)  {
a1ef721998-04-05Fredrik Hübinette (Hubbe)  ERRNO=errno; push_int(0); return;
c201101998-03-25Henrik Grubbström (Grubba)  }
da7e5d2009-02-23Henrik Grubbström (Grubba)  push_new_fd_object(fd_fd_factory_fun_num, fd, THIS->open_mode, THIS->open_mode); o = Pike_sp[-1].u.object; f = ((struct my_file *)
017b572011-10-28Henrik Grubbström (Grubba)  (o->storage + o->prog->inherits[SUBTYPEOF(Pike_sp[-1])].storage_offset));
a1ef721998-04-05Fredrik Hübinette (Hubbe)  ERRNO=0;
10dac82004-04-05Martin Stjernholm  low_dup(o, f, THIS);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
5761a32008-06-13Henrik Grubbström (Grubba) /*! @decl int(0..1) open_socket(int|void port, string|void addr, @
0e77e92008-12-14Marcus Comstedt  *! int|string|void family_hint)
9c052f2001-02-15Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_open_socket(INT32 args) {
c657d01997-01-29Fredrik Hübinette (Hubbe)  int fd;
20c99e2003-04-24Marcus Comstedt  int family=-1;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  close_fd();
20c99e2003-04-24Marcus Comstedt 
017b572011-10-28Henrik Grubbström (Grubba)  if (args > 2 && TYPEOF(Pike_sp[2-args]) == PIKE_T_INT &&
242ac52003-04-26Marcus Comstedt  Pike_sp[2-args].u.integer != 0) family = Pike_sp[2-args].u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  else if (args > 2 && TYPEOF(Pike_sp[2-args]) == PIKE_T_STRING &&
0e77e92008-12-14Marcus Comstedt  !Pike_sp[2-args].u.string->size_shift) { PIKE_SOCKADDR addr;
2e005f2014-02-25Per Hedbor  get_inet_addr(&addr, (char *) STR0(Pike_sp[2-args].u.string), NULL, -1, 0);
0e77e92008-12-14Marcus Comstedt  family = SOCKADDR_FAMILY(addr);
f010202011-11-16Tobias S. Josefowitz  INVALIDATE_CURRENT_TIME();
0e77e92008-12-14Marcus Comstedt  }
242ac52003-04-26Marcus Comstedt 
017b572011-10-28Henrik Grubbström (Grubba)  if (args && TYPEOF(Pike_sp[-args]) == PIKE_T_INT &&
242ac52003-04-26Marcus Comstedt  Pike_sp[-args].u.integer < 0) {
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
20c99e2003-04-24Marcus Comstedt  args = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
34a1df2005-04-08Henrik Grubbström (Grubba) /* fprintf(stderr, "file_open_socket: family: %d\n", family); */
a9130c1997-03-27Henrik Grubbström (Grubba)  if (args) {
cf77092003-04-24Marcus Comstedt  PIKE_SOCKADDR addr;
486dbe2003-04-23Marcus Comstedt  int addr_len;
3c0d582003-04-22Marcus Comstedt  char *name;
a9130c1997-03-27Henrik Grubbström (Grubba)  int o;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-args]) != PIKE_T_INT && (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING ||
3c0d582003-04-22Marcus Comstedt  Pike_sp[-args].u.string->size_shift)) {
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("open_socket", 1, "int|string(8bit)");
a9130c1997-03-27Henrik Grubbström (Grubba)  }
20c99e2003-04-24Marcus Comstedt  if (args > 1 && !UNSAFE_IS_ZERO(&Pike_sp[1-args])) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[1-args]) != PIKE_T_STRING) {
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("open_socket", 2, "string");
a9130c1997-03-27Henrik Grubbström (Grubba)  }
3c0d582003-04-22Marcus Comstedt  name = Pike_sp[1-args].u.string->str;
a9130c1997-03-27Henrik Grubbström (Grubba)  } else {
3c0d582003-04-22Marcus Comstedt  name = NULL;
a9130c1997-03-27Henrik Grubbström (Grubba)  }
486dbe2003-04-23Marcus Comstedt  addr_len = get_inet_addr(&addr, name,
017b572011-10-28Henrik Grubbström (Grubba)  (TYPEOF(Pike_sp[-args]) == PIKE_T_STRING?
486dbe2003-04-23Marcus Comstedt  Pike_sp[-args].u.string->str : NULL),
017b572011-10-28Henrik Grubbström (Grubba)  (TYPEOF(Pike_sp[-args]) == PIKE_T_INT?
486dbe2003-04-23Marcus Comstedt  Pike_sp[-args].u.integer : -1), 0);
f010202011-11-16Tobias S. Josefowitz  INVALIDATE_CURRENT_TIME();
a9130c1997-03-27Henrik Grubbström (Grubba) 
20c99e2003-04-24Marcus Comstedt  fd=fd_socket((family<0? SOCKADDR_FAMILY(addr):family), SOCK_STREAM, 0); if(fd < 0) { ERRNO=errno; pop_n_elems(args); push_int(0); return; }
a9130c1997-03-27Henrik Grubbström (Grubba)  o=1;
5740881998-01-01Fredrik Hübinette (Hubbe)  if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) {
a9130c1997-03-27Henrik Grubbström (Grubba)  ERRNO=errno;
ae39322003-09-30Martin Stjernholm  while (fd_close(fd) && errno == EINTR) {} errno = ERRNO;
a9130c1997-03-27Henrik Grubbström (Grubba)  pop_n_elems(args); push_int(0); return; }
3020732012-01-30Henrik Grubbström (Grubba) 
2266322012-01-31Henrik Grubbström (Grubba) #if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
3020732012-01-30Henrik Grubbström (Grubba)  if ((family<0? SOCKADDR_FAMILY(addr):family) == AF_INET6) { /* Attempt to enable dual-stack (ie mapped IPv4 adresses). * Needed on WIN32. * cf http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx */ o = 0; fd_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&o, sizeof(int)); } #endif
88686c2009-06-29Henrik Grubbström (Grubba) #ifdef SO_REUSEPORT /* FreeBSD 7.x wants this to reuse portnumbers. * Linux 2.6.x seems to have reserved a slot for the option, but not * enabled it. Survive libc's with the option on kernels without.
83ad202016-12-04Henrik Grubbström (Grubba)  * * The emulated Linux runtime on MS Windows 10 fails this with EINVAL.
88686c2009-06-29Henrik Grubbström (Grubba)  */
3b30902009-06-29Henrik Grubbström (Grubba)  o=1;
88686c2009-06-29Henrik Grubbström (Grubba)  if((fd_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&o, sizeof(int)) < 0) #ifdef ENOPROTOOPT && (errno != ENOPROTOOPT) #endif
83ad202016-12-04Henrik Grubbström (Grubba) #ifdef EINVAL && (errno != EINVAL) #endif
88686c2009-06-29Henrik Grubbström (Grubba) #ifdef WSAENOPROTOOPT && (errno != WSAENOPROTOOPT) #endif
83ad202016-12-04Henrik Grubbström (Grubba)  ){
88686c2009-06-29Henrik Grubbström (Grubba)  ERRNO=errno; while (fd_close(fd) && errno == EINTR) {} errno = ERRNO; pop_n_elems(args); push_int(0); return; } #endif /* SO_REUSEPORT */
486dbe2003-04-23Marcus Comstedt  if (fd_bind(fd, (struct sockaddr *)&addr, addr_len) < 0) {
a9130c1997-03-27Henrik Grubbström (Grubba)  ERRNO=errno;
ae39322003-09-30Martin Stjernholm  while (fd_close(fd) && errno == EINTR) {} errno = ERRNO;
a9130c1997-03-27Henrik Grubbström (Grubba)  pop_n_elems(args); push_int(0); return; }
20c99e2003-04-24Marcus Comstedt  } else {
e784c82006-05-31Henrik Grubbström (Grubba)  int o;
20c99e2003-04-24Marcus Comstedt  fd=fd_socket((family<0? AF_INET:family), SOCK_STREAM, 0); if(fd < 0) { ERRNO=errno; pop_n_elems(args); push_int(0); return; }
e784c82006-05-31Henrik Grubbström (Grubba)  o=1; if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) { ERRNO=errno; while (fd_close(fd) && errno == EINTR) {} errno = ERRNO; pop_n_elems(args); push_int(0); return; }
3020732012-01-30Henrik Grubbström (Grubba) 
2266322012-01-31Henrik Grubbström (Grubba) #if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
3020732012-01-30Henrik Grubbström (Grubba)  if ((family<0? AF_INET:family) == AF_INET6) { /* Attempt to enable dual-stack (ie mapped IPv4 adresses). * Needed on WIN32. * cf http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx */ o = 0; fd_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&o, sizeof(int)); } #endif
88686c2009-06-29Henrik Grubbström (Grubba) #ifdef SO_REUSEPORT /* FreeBSD 7.x wants this to reuse portnumbers. * Linux 2.6.x seems to have reserved a slot for the option, but not * enabled it. Survive libc's with the option on kernels without.
83ad202016-12-04Henrik Grubbström (Grubba)  * * The emulated Linux runtime on MS Windows 10 fails this with EINVAL.
88686c2009-06-29Henrik Grubbström (Grubba)  */
3b30902009-06-29Henrik Grubbström (Grubba)  o=1;
88686c2009-06-29Henrik Grubbström (Grubba)  if((fd_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&o, sizeof(int)) < 0) #ifdef ENOPROTOOPT && (errno != ENOPROTOOPT) #endif
83ad202016-12-04Henrik Grubbström (Grubba) #ifdef EINVAL && (errno != EINVAL) #endif
88686c2009-06-29Henrik Grubbström (Grubba) #ifdef WSAENOPROTOOPT && (errno != WSAENOPROTOOPT) #endif
83ad202016-12-04Henrik Grubbström (Grubba)  ){
88686c2009-06-29Henrik Grubbström (Grubba)  ERRNO=errno; while (fd_close(fd) && errno == EINTR) {} errno = ERRNO; pop_n_elems(args); push_int(0); return; } #endif /* SO_REUSEPORT */
a9130c1997-03-27Henrik Grubbström (Grubba)  }
41d7dc2007-05-20Henrik Grubbström (Grubba)  init_fd(fd, FILE_READ | FILE_WRITE | fd_query_properties(fd, SOCKET_CAPABILITIES), 0);
c657d01997-01-29Fredrik Hübinette (Hubbe)  my_set_close_on_exec(fd,1);
10dac82004-04-05Martin Stjernholm  change_fd_for_box (&THIS->box, FD);
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(1); }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int(0..1) set_keepalive(int(0..1) on_off)
b335e12014-08-29Chris Angelico  *! *! Equivalent to setsockopt(Stdio.SO_KEEPALIVE, on_off), but will set errno *! if SO_KEEPALIVE is not supported, rather than issuing a compilation error *! for the missing constant.
9c052f2001-02-15Henrik Grubbström (Grubba)  */
c657d01997-01-29Fredrik Hübinette (Hubbe) static void file_set_keepalive(INT32 args) { int tmp, i;
8e14db1999-04-01Wilhelm Köhler  INT_TYPE t;
69c0aa2014-08-25Martin Nilsson  get_all_args("set_keepalive", args, "%i", &t);
8e14db1999-04-01Wilhelm Köhler  /* In case int and INT_TYPE have different sizes */ tmp = t;
de781c1998-05-22Henrik Grubbström (Grubba) #ifdef SO_KEEPALIVE
8e14db1999-04-01Wilhelm Köhler  i = fd_setsockopt(FD,SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
c657d01997-01-29Fredrik Hübinette (Hubbe)  if(i) { ERRNO=errno; }else{ ERRNO=0; }
de781c1998-05-22Henrik Grubbström (Grubba) #else /* !SO_KEEPALIVE */ #ifdef ENOTSUP
ae39322003-09-30Martin Stjernholm  ERRNO = errno = ENOTSUP;
de781c1998-05-22Henrik Grubbström (Grubba) #else /* !ENOTSUP */ #ifdef ENOTTY
ae39322003-09-30Martin Stjernholm  ERRNO = errno = ENOTTY;
de781c1998-05-22Henrik Grubbström (Grubba) #else /* !ENOTTY */
ae39322003-09-30Martin Stjernholm  ERRNO = errno = EIO;
de781c1998-05-22Henrik Grubbström (Grubba) #endif /* ENOTTY */ #endif /* ENOTSUP */ #endif /* SO_KEEPALIVE */
c657d01997-01-29Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(!i); }
f743d52015-05-04Chris Angelico /*! @decl int(0..1) setsockopt(int level,int opt,int state)
c8f8112014-08-29Chris Angelico  *! *! Set socket options like Stdio.SO_KEEPALIVE. This function is always *! available; the presence or absence of the option constants indicates *! availability of those features. *! *! @returns *! 1 if successful, 0 if not (and sets errno()) *! *! @seealso *! @[set_keepalive()] */ static void file_setsockopt(INT32 args) {
f743d52015-05-04Chris Angelico  int tmp, i, opt, level; INT_TYPE o, t, l;
c8f8112014-08-29Chris Angelico 
f743d52015-05-04Chris Angelico  get_all_args("setsockopt", args, "%i%i%i", &l, &o, &t);
c8f8112014-08-29Chris Angelico  /* In case int and INT_TYPE have different sizes */
f743d52015-05-04Chris Angelico  tmp = t; opt = o; level = l;
c8f8112014-08-29Chris Angelico 
f743d52015-05-04Chris Angelico  i = fd_setsockopt(FD, level, opt, (char *)&tmp, sizeof(tmp));
c8f8112014-08-29Chris Angelico  if(i) { ERRNO=errno; }else{ ERRNO=0; } pop_n_elems(args); push_int(!i); }
baffcc2002-08-16Henrik Grubbström (Grubba) #ifdef HAVE_SYS_UN_H
3bedfb2002-05-19Per Hedbor #include <sys/un.h>
6038152003-02-21Henrik Grubbström (Grubba) #ifndef PATH_MAX #ifdef _POSIX_PATH_MAX #define PATH_MAX _POSIX_PATH_MAX #else /* !_POSIX_PATH_MAX */ #define PATH_MAX 255 /* Minimum according to POSIX. */ #endif /* _POSIX_PATH_MAX */ #endif /* !PATH_MAX */
3bedfb2002-05-19Per Hedbor /*! @decl int(0..1) connect_unix( string filename ) *! *! Open a UNIX domain socket connection to the specified destination. *!
0065eb2009-07-23Henrik Grubbström (Grubba)  *! @param filename *! Filename to create. *!
3bedfb2002-05-19Per Hedbor  *! In nonblocking mode, success is indicated with the write-callback, *! and failure with the close-callback or the read_oob-callback. *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! Returns @expr{1@} on success, and @expr{0@} on failure.
3bedfb2002-05-19Per Hedbor  *! *! @note
cbe8c92003-04-07Martin Nilsson  *! In nonblocking mode @expr{0@} (zero) may be returned and @[errno()] set *! to @tt{EWOULDBLOCK@} or @tt{WSAEWOULDBLOCK@}. This should not be regarded
3bedfb2002-05-19Per Hedbor  *! as a connection failure.
0065eb2009-07-23Henrik Grubbström (Grubba)  *! *! @note *! @[path] had a quite restrictive length limit (~100 characters) *! prior to Pike 7.8.334.
3bedfb2002-05-19Per Hedbor  */ static void file_connect_unix( INT32 args ) {
0065eb2009-07-23Henrik Grubbström (Grubba)  struct sockaddr_un *name;
16e0672010-02-24Henrik Grubbström (Grubba)  int addr_len;
3bedfb2002-05-19Per Hedbor  int tmp;
06bd612016-01-26Martin Nilsson  if( args != 1 ) SIMPLE_WRONG_NUM_ARGS_ERROR("connect_unix", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if( (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING) ||
0065eb2009-07-23Henrik Grubbström (Grubba)  (Pike_sp[-args].u.string->size_shift) )
3bedfb2002-05-19Per Hedbor  Pike_error("Illegal argument. Expected string(8bit)\n");
16e0672010-02-24Henrik Grubbström (Grubba)  /* NOTE: Some operating systems (eg Linux 2.6) do not support * paths longer than what fits into a plain struct sockaddr_un. */ addr_len = sizeof(struct sockaddr_un) + Pike_sp[-args].u.string->len + 1 -
e5c7c22010-02-24Henrik Grubbström (Grubba)  sizeof(name->sun_path);
16e0672010-02-24Henrik Grubbström (Grubba)  name = xalloc(addr_len);
0065eb2009-07-23Henrik Grubbström (Grubba)  name->sun_family=AF_UNIX; strcpy( name->sun_path, Pike_sp[-args].u.string->str );
9670672009-07-23Henrik Grubbström (Grubba) #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN /* Length including NUL. */ name->sun_len = Pike_sp[-args].u.string->len + 1; #endif
4e0eca2002-06-10Henrik Grubbström (Grubba)  pop_n_elems(args);
10dac82004-04-05Martin Stjernholm  close_fd(); change_fd_for_box (&THIS->box, socket(AF_UNIX,SOCK_STREAM,0));
3bedfb2002-05-19Per Hedbor  if( FD < 0 ) {
0065eb2009-07-23Henrik Grubbström (Grubba)  free(name);
4e0eca2002-06-10Henrik Grubbström (Grubba)  ERRNO = errno;
3bedfb2002-05-19Per Hedbor  push_int(0); return; } init_fd(FD, FILE_READ | FILE_WRITE
98b4c22010-02-18Henrik Grubbström (Grubba)  | fd_query_properties(FD, UNIX_SOCKET_CAPABILITIES), 0);
4e0eca2002-06-10Henrik Grubbström (Grubba)  my_set_close_on_exec(FD, 1);
3bedfb2002-05-19Per Hedbor 
0065eb2009-07-23Henrik Grubbström (Grubba)  do {
16e0672010-02-24Henrik Grubbström (Grubba)  tmp=connect(FD,(void *)name, addr_len);
0065eb2009-07-23Henrik Grubbström (Grubba)  } while ((tmp < 0) && (errno == EINTR)); free(name);
4e0eca2002-06-10Henrik Grubbström (Grubba)  if (tmp == -1) { ERRNO = errno; push_int(0); } else { push_int(1); }
3bedfb2002-05-19Per Hedbor }
baffcc2002-08-16Henrik Grubbström (Grubba) #endif /* HAVE_SYS_UN_H */
3bedfb2002-05-19Per Hedbor 
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl int(0..1) connect(string dest_addr, int dest_port) *! @decl int(0..1) connect(string dest_addr, int dest_port, @ *! string src_addr, int src_port)
86eae42014-08-26Per Hedbor  *! @decl string(0..255)|int(0..0) connect(string dest_addr, int dest_port, @ *! string|int(0..0) src_addr, int|int(0..0) src_port, @ *! string(0..255) data)
02e2012001-06-25Henrik Grubbström (Grubba)  *! *! Open a TCP/IP connection to the specified destination. *! *! In nonblocking mode, success is indicated with the write-callback, *! and failure with the close-callback or the read_oob-callback. *!
86eae42014-08-26Per Hedbor  *! If the @[data] argument is included the socket will use *! TCP_FAST_OPEN if available, if not the data will @i{not be *! sent@}. In the data case the function either returns the data *! that has not been sent (only one packet can be sent with this *! option) or 0 if the connection failed immediately. *!
02e2012001-06-25Henrik Grubbström (Grubba)  *! @returns
86eae42014-08-26Per Hedbor  *! Returns @expr{1@} or the remaining @expr{data@} on success, and *! @expr{0@} on failure.
02e2012001-06-25Henrik Grubbström (Grubba)  *! *! @note
cbe8c92003-04-07Martin Nilsson  *! In nonblocking mode @expr{0@} (zero) may be returned and @[errno()] set *! to @tt{EWOULDBLOCK@} or @tt{WSAEWOULDBLOCK@}. This should not be regarded
02e2012001-06-25Henrik Grubbström (Grubba)  *! as a connection failure.
86eae42014-08-26Per Hedbor  *!
9c052f2001-02-15Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_connect(INT32 args) {
cf77092003-04-24Marcus Comstedt  PIKE_SOCKADDR addr;
486dbe2003-04-23Marcus Comstedt  int addr_len;
3357232000-03-13Henrik Grubbström (Grubba)  struct pike_string *dest_addr = NULL; struct pike_string *src_addr = NULL;
86eae42014-08-26Per Hedbor  struct pike_string *data = NULL;
3c0d582003-04-22Marcus Comstedt  struct svalue *dest_port = NULL; struct svalue *src_port = NULL;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a1933a2004-11-15Martin Stjernholm  int tmp, was_closed = FD < 0;
86eae42014-08-26Per Hedbor  int fd, sent = 0;
b1f1962014-10-01Henrik Grubbström (Grubba)  int nb_mode;
385ad32014-10-02Henrik Grubbström (Grubba)  int old_events; int e;
ee71702000-01-30Per Hedbor 
13670c2015-05-25Martin Nilsson  if (args < 4)
2c054f2014-08-26Per Hedbor  {
69c0aa2014-08-25Martin Nilsson  get_all_args("connect", args, "%S%*", &dest_addr, &dest_port);
2c054f2014-08-26Per Hedbor  } else if( args == 5 ) {
86eae42014-08-26Per Hedbor  struct svalue *src_sv; get_all_args("connect", args, "%S%*%*%*%S", &dest_addr, &dest_port, &src_sv, &src_port, &data); if(TYPEOF(*src_sv) != PIKE_T_INT ) { if (TYPEOF(*src_sv) != PIKE_T_STRING || src_sv->u.string->size_shift)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("connect", 3, "int|string(8bit)");
86eae42014-08-26Per Hedbor  src_addr = src_sv->u.string; }
3357232000-03-13Henrik Grubbström (Grubba)  } else {
69c0aa2014-08-25Martin Nilsson  get_all_args("connect", args, "%S%*%S%*",
3357232000-03-13Henrik Grubbström (Grubba)  &dest_addr, &dest_port, &src_addr, &src_port); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*dest_port) != PIKE_T_INT && (TYPEOF(*dest_port) != PIKE_T_STRING || dest_port->u.string->size_shift))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("connect", 2, "int|string(8bit)");
3c0d582003-04-22Marcus Comstedt 
017b572011-10-28Henrik Grubbström (Grubba)  if(src_port && TYPEOF(*src_port) != PIKE_T_INT && (TYPEOF(*src_port) != PIKE_T_STRING || src_port->u.string->size_shift))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("connect", 4, "int|string(8bit)");
3c0d582003-04-22Marcus Comstedt 
4368dd2010-05-26Henrik Grubbström (Grubba) /* fprintf(stderr, "connect: family: %d\n", SOCKADDR_FAMILY(addr)); */
20c99e2003-04-24Marcus Comstedt  addr_len = get_inet_addr(&addr, dest_addr->str,
017b572011-10-28Henrik Grubbström (Grubba)  (TYPEOF(*dest_port) == PIKE_T_STRING?
20c99e2003-04-24Marcus Comstedt  dest_port->u.string->str : NULL),
017b572011-10-28Henrik Grubbström (Grubba)  (TYPEOF(*dest_port) == PIKE_T_INT?
20c99e2003-04-24Marcus Comstedt  dest_port->u.integer : -1), 0);
f010202011-11-16Tobias S. Josefowitz  INVALIDATE_CURRENT_TIME();
20c99e2003-04-24Marcus Comstedt 
a1933a2004-11-15Martin Stjernholm  if(was_closed)
c657d01997-01-29Fredrik Hübinette (Hubbe)  {
86eae42014-08-26Per Hedbor  if (!src_addr) {
242ac52003-04-26Marcus Comstedt  push_int(-1); push_int(0);
20c99e2003-04-24Marcus Comstedt  push_int(SOCKADDR_FAMILY(addr));
242ac52003-04-26Marcus Comstedt  file_open_socket(3);
3357232000-03-13Henrik Grubbström (Grubba)  } else {
3c0d582003-04-22Marcus Comstedt  push_svalue(src_port);
3357232000-03-13Henrik Grubbström (Grubba)  ref_push_string(src_addr); file_open_socket(2); }
9f516a2001-12-16Martin Stjernholm  if(UNSAFE_IS_ZERO(Pike_sp-1) || FD < 0)
b1c4582003-01-11Martin Nilsson  Pike_error("Stdio.File->connect(): Failed to open socket.\n");
c657d01997-01-29Fredrik Hübinette (Hubbe)  pop_stack(); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b1f1962014-10-01Henrik Grubbström (Grubba)  nb_mode = !!(THIS->open_mode & FILE_NONBLOCKING);
385ad32014-10-02Henrik Grubbström (Grubba)  /* Inhibit the backend for this fd while connect(2) is running. */ if ((old_events = THIS->box.events)) { set_fd_callback_events(&(THIS->box), 0, THIS->box.flags); }
86eae42014-08-26Per Hedbor  fd = FD; THREADS_ALLOW(); for(;;)
3e11ee2010-02-18Stephen R. van den Berg  {
86eae42014-08-26Per Hedbor #ifdef MSG_FASTOPEN if( data ) { tmp = sendto(fd, data->str, data->len, MSG_FASTOPEN, (struct sockaddr *)&addr, addr_len ); } else
7aeec82010-02-18Stephen R. van den Berg #endif
86eae42014-08-26Per Hedbor  { tmp=fd_connect(fd, (struct sockaddr *)&addr, addr_len); } if( tmp<0 && (errno==EINTR)) continue;
3e11ee2010-02-18Stephen R. van den Berg  break; }
86eae42014-08-26Per Hedbor  THREADS_DISALLOW();
385ad32014-10-02Henrik Grubbström (Grubba)  e = errno; if (old_events) { /* Reenable the backend. */ set_fd_callback_events(&(THIS->box), old_events, THIS->box.flags); } errno = e; /* NB: On success in threaded callback-mode, some other thread may * have messed with us before THREADS_DISALLOW() has finished.
b1f1962014-10-01Henrik Grubbström (Grubba)  * * We thus mustn't look at the current settings of ourselves, as * they may have been changed since before the fd_connect() call. */
07513e1996-10-04Fredrik Hübinette (Hubbe) 
31b3b91998-04-17Fredrik Hübinette (Hubbe)  if(tmp < 0 #ifdef EINPROGRESS
b1f1962014-10-01Henrik Grubbström (Grubba)  && !(errno == EINPROGRESS && nb_mode)
b5d9fb2001-12-05Henrik Grubbström (Grubba) #endif #ifdef WSAEWOULDBLOCK
b1f1962014-10-01Henrik Grubbström (Grubba)  && !(errno == WSAEWOULDBLOCK && nb_mode)
b5d9fb2001-12-05Henrik Grubbström (Grubba) #endif #ifdef EWOULDBLOCK
b1f1962014-10-01Henrik Grubbström (Grubba)  && !(errno == EWOULDBLOCK && nb_mode)
31b3b91998-04-17Fredrik Hübinette (Hubbe) #endif )
5267b71995-08-09Fredrik Hübinette (Hubbe)  { /* something went wrong */
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=errno;
a1933a2004-11-15Martin Stjernholm  if (was_closed) { while (fd_close (FD) && errno == EINTR) {} change_fd_for_box (&THIS->box, -1); errno = ERRNO; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(0); }else{
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=0;
86eae42014-08-26Per Hedbor  if( data ) { push_string( make_shared_binary_string( data->str + tmp, data->len-tmp ) ); stack_pop_n_elems_keep_top( args ); } else { pop_n_elems(args); push_int(1); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl string query_address() *! @decl string query_address(int(0..1) local) *! *! Get address and port of a socket end-point. *!
0fb2502003-04-23Henrik Grubbström (Grubba)  *! @param local
5601732004-11-30Martin Stjernholm  *! If the argument @[local] is not specified, or is @expr{0@} *! (zero), the remote end-point is returned. Otherwise, if @[local] *! is @expr{1@}, the local end-point is returned.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
0fb2502003-04-23Henrik Grubbström (Grubba)  *! @returns *! This function returns the address and port of a socket end-point *! on the form @expr{"x.x.x.x port"@} (IPv4) or
4368dd2010-05-26Henrik Grubbström (Grubba)  *! @expr{"x:x:x:x:x:x:x:x port"@} (IPv6). IPv6 addresses *! may use the contracted syntax.
9c052f2001-02-15Henrik Grubbström (Grubba)  *!
0fb2502003-04-23Henrik Grubbström (Grubba)  *! If this file is not a socket, is not connected, or some other
9269902008-05-12Martin Stjernholm  *! error occurs, @expr{0@} (zero) is returned and @[errno()] will *! return the error code. *! *! @throws *! An error is thrown if the socket (or file) isn't open.
9c052f2001-02-15Henrik Grubbström (Grubba)  *! *! @seealso *! @[connect()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_query_address(INT32 args) {
cf77092003-04-24Marcus Comstedt  PIKE_SOCKADDR addr;
7efa531997-09-23Henrik Grubbström (Grubba)  int i;
9269902008-05-12Martin Stjernholm  char buffer[496];
0fb2502003-04-23Henrik Grubbström (Grubba)  /* XOPEN GROUP thinks this variable should be a size_t. * BSD thinks it should be an int.
634a571998-08-07Henrik Grubbström (Grubba)  */
7c6a531998-08-07Henrik Grubbström (Grubba)  ACCEPT_SIZE_T len;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f0d73c1995-11-04Fredrik Hübinette (Hubbe)  if(FD <0)
b1c4582003-01-11Martin Nilsson  Pike_error("Stdio.File->query_address(): Connection not open.\n");
f0d73c1995-11-04Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  len=sizeof(addr);
9f516a2001-12-16Martin Stjernholm  if(args > 0 && !UNSAFE_IS_ZERO(Pike_sp-args))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
5740881998-01-01Fredrik Hübinette (Hubbe)  i=fd_getsockname(FD,(struct sockaddr *)&addr,&len);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
5740881998-01-01Fredrik Hübinette (Hubbe)  i=fd_getpeername(FD,(struct sockaddr *)&addr,&len);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } pop_n_elems(args);
748b3c2011-01-24Martin Stjernholm  if(i < 0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  ERRNO=errno;
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_int(0);
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  return;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
9269902008-05-12Martin Stjernholm 
6a539c2009-05-28Henrik Grubbström (Grubba) #ifdef fd_inet_ntop if(!fd_inet_ntop(SOCKADDR_FAMILY(addr), SOCKADDR_IN_ADDR(addr), buffer, sizeof(buffer)-20))
41a68a2008-05-03Marcus Comstedt  { ERRNO=errno; push_int(0); return; } #else if(SOCKADDR_FAMILY(addr) == AF_INET) {
9269902008-05-12Martin Stjernholm  char *q = inet_ntoa(*SOCKADDR_IN_ADDR(addr));
41a68a2008-05-03Marcus Comstedt  strncpy(buffer,q,sizeof(buffer)-20); buffer[sizeof(buffer)-20]=0; }else{ #ifdef EAFNOSUPPORT ERRNO=EAFNOSUPPORT;
cae06e2003-04-22Marcus Comstedt #else
41a68a2008-05-03Marcus Comstedt  ERRNO=EINVAL; #endif push_int(0); return; }
cae06e2003-04-22Marcus Comstedt #endif
486dbe2003-04-23Marcus Comstedt  sprintf(buffer+strlen(buffer)," %d",(int)(ntohs(addr.ipv4.sin_port)));
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ca02192010-05-27Henrik Grubbström (Grubba)  /* NOTE: IPv6-mapped IPv4 addresses may only connect to other IPv4 addresses. * * Make the Pike-level code believe it has an actual IPv4 address * when getting a mapped address (::FFFF:a.b.c.d).
4368dd2010-05-26Henrik Grubbström (Grubba)  */
ca02192010-05-27Henrik Grubbström (Grubba)  if ((!strncmp(buffer, "::FFFF:", 7) || !strncmp(buffer, "::ffff:", 7)) && !strchr(buffer + 7, ':')) { push_text(buffer+7); } else { push_text(buffer); }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl void create(string filename) *! @decl void create(string filename, string mode)
7363b72011-09-07Henrik Grubbström (Grubba)  *! @decl void create(string filename, string mode, int access)
9c052f2001-02-15Henrik Grubbström (Grubba)  *! @decl void create(int fd) *! @decl void create(int fd, string mode) *! *! See @[open()]. *! *! @seealso *! @[open()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void file_create(INT32 args) {
c9a7461999-09-29Mirar (Pontus Hagland)  if(!args) return;
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-args]) != PIKE_T_STRING && TYPEOF(Pike_sp[-args]) != PIKE_T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("create", 1, "int|string");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a1ef721998-04-05Fredrik Hübinette (Hubbe)  close_fd(); file_open(args);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
864d3c1998-01-29Fredrik Hübinette (Hubbe) #ifdef _REENTRANT struct new_thread_data {
514e971998-03-02Fredrik Hübinette (Hubbe)  INT32 from, to;
c744452006-03-05Marcus Comstedt  char buffer[READ_BUFFER];
864d3c1998-01-29Fredrik Hübinette (Hubbe) };
7267ee1999-05-13Fredrik Hübinette (Hubbe) static TH_RETURN_TYPE proxy_thread(void * data)
864d3c1998-01-29Fredrik Hübinette (Hubbe) { struct new_thread_data *p=(struct new_thread_data *)data; while(1) {
b96ca92000-08-19Henrik Grubbström (Grubba)  ptrdiff_t len, w;
c744452006-03-05Marcus Comstedt  len = fd_read(p->from, p->buffer, READ_BUFFER);
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  if(len==0) break;
864d3c1998-01-29Fredrik Hübinette (Hubbe)  if(len<0) { if(errno==EINTR) continue;
6cb1841998-05-05Fredrik Hübinette (Hubbe) /* fprintf(stderr,"Threaded read failed with errno = %d\n",errno); */
864d3c1998-01-29Fredrik Hübinette (Hubbe)  break; } w=0; while(w<len) {
c744452006-03-05Marcus Comstedt  ptrdiff_t wl = fd_write(p->to, p->buffer+w, len-w);
e10da82009-06-29Henrik Grubbström (Grubba)  if (!wl) { goto close_and_exit; }
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  if(wl<0) { if(errno==EINTR) continue;
6cb1841998-05-05Fredrik Hübinette (Hubbe) /* fprintf(stderr,"Threaded write failed with errno = %d\n",errno); */
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  break; }
864d3c1998-01-29Fredrik Hübinette (Hubbe)  w+=wl; } }
e10da82009-06-29Henrik Grubbström (Grubba)  close_and_exit:
6cb1841998-05-05Fredrik Hübinette (Hubbe) /* fprintf(stderr,"Closing %d and %d\n",p->to,p->from); */
ae39322003-09-30Martin Stjernholm  while (fd_close(p->to) && errno == EINTR) {} while (fd_close(p->from) && errno == EINTR) {}
5715cc2001-11-01Martin Stjernholm  low_mt_lock_interpreter(); /* Can run even if threads_disabled. */
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  num_threads--;
c91f892000-04-19Martin Stjernholm  mt_unlock_interpreter();
0ec7522014-04-27Martin Nilsson  free(p);
9005641999-05-17Fredrik Hübinette (Hubbe)  th_exit(0);
864d3c1998-01-29Fredrik Hübinette (Hubbe)  return 0; }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl void proxy(Stdio.File from) *! *! Starts a thread that asynchronously copies data from @[from] *! to this file. *! *! @seealso *! @[Stdio.sendfile()] */
864d3c1998-01-29Fredrik Hübinette (Hubbe) void file_proxy(INT32 args) {
a1ef721998-04-05Fredrik Hübinette (Hubbe)  struct my_file *f;
864d3c1998-01-29Fredrik Hübinette (Hubbe)  struct new_thread_data *p;
641d5c1998-04-09Fredrik Hübinette (Hubbe)  int from, to;
864d3c1998-01-29Fredrik Hübinette (Hubbe)  THREAD_T id;
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  check_all_args("Stdio.File->proxy",args, BIT_OBJECT,0);
5923b12000-07-06Fredrik Hübinette (Hubbe)  f=get_file_storage(Pike_sp[-args].u.object);
864d3c1998-01-29Fredrik Hübinette (Hubbe)  if(!f)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("proxy", 1, "Stdio.File");
864d3c1998-01-29Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  from=fd_dup(f->box.fd);
641d5c1998-04-09Fredrik Hübinette (Hubbe)  if(from<0) { ERRNO=errno;
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to dup proxy fd. (errno=%d)\n",errno);
641d5c1998-04-09Fredrik Hübinette (Hubbe)  } to=fd_dup(FD);
c1b8f12008-06-29Henrik Grubbström (Grubba)  if(to<0)
641d5c1998-04-09Fredrik Hübinette (Hubbe)  { ERRNO=errno;
ae39322003-09-30Martin Stjernholm  while (fd_close(from) && errno == EINTR) {} errno = ERRNO;
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to dup proxy fd.\n");
641d5c1998-04-09Fredrik Hübinette (Hubbe)  }
ee71702000-01-30Per Hedbor 
864d3c1998-01-29Fredrik Hübinette (Hubbe)  p=ALLOC_STRUCT(new_thread_data);
641d5c1998-04-09Fredrik Hübinette (Hubbe)  p->from=from; p->to=to;
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  num_threads++; if(th_create_small(&id,proxy_thread,p))
864d3c1998-01-29Fredrik Hübinette (Hubbe)  {
0ec7522014-04-27Martin Nilsson  free(p);
c1b8f12008-06-29Henrik Grubbström (Grubba)  while (fd_close(from) && errno == EINTR) {} while (fd_close(to) && errno == EINTR) {}
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to create thread.\n");
864d3c1998-01-29Fredrik Hübinette (Hubbe)  }
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
864d3c1998-01-29Fredrik Hübinette (Hubbe)  th_destroy(& id); }
097de92006-07-05Martin Stjernholm PMOD_EXPORT void create_proxy_pipe(struct object *o, int for_reading)
864d3c1998-01-29Fredrik Hübinette (Hubbe) { struct object *n,*n2; push_object(n=clone_object(file_program,0)); push_int(fd_INTERPROCESSABLE); apply(n,"pipe",1);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) != PIKE_T_OBJECT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to create proxy pipe (errno=%d)!\n",get_file_storage(n)->my_errno);
5923b12000-07-06Fredrik Hübinette (Hubbe)  n2=Pike_sp[-1].u.object;
5a7ab61998-01-31Fredrik Hübinette (Hubbe)  /* Stack is now: pipe(read), pipe(write) */
864d3c1998-01-29Fredrik Hübinette (Hubbe)  if(for_reading) { ref_push_object(o); apply(n2,"proxy",1); pop_n_elems(2); }else{ /* Swap */
5923b12000-07-06Fredrik Hübinette (Hubbe)  Pike_sp[-2].u.object=n2; Pike_sp[-1].u.object=n;
864d3c1998-01-29Fredrik Hübinette (Hubbe)  apply(o,"proxy",1); pop_stack(); } } #endif
ee71702000-01-30Per Hedbor #if defined(HAVE_FD_FLOCK) || defined(HAVE_FD_LOCKF)
d386e61998-03-20Fredrik Hübinette (Hubbe)  static struct program * file_lock_key_program; struct file_lock_key_storage {
a1ef721998-04-05Fredrik Hübinette (Hubbe)  struct my_file *f;
e8a96c2000-08-27Henrik Grubbström (Grubba)  struct object *file;
d386e61998-03-20Fredrik Hübinette (Hubbe) #ifdef _REENTRANT
1d456f2003-02-20Henrik Grubbström (Grubba)  struct thread_state *owner; struct object *owner_obj;
d386e61998-03-20Fredrik Hübinette (Hubbe) #endif }; #define OB2KEY(O) ((struct file_lock_key_storage *)((O)->storage)) static void low_file_lock(INT32 args, int flags) { int ret,fd=FD; struct object *o;
13670c2015-05-25Martin Nilsson 
5fc6062001-01-27Fredrik Hübinette (Hubbe)  destruct_objects_to_destruct();
d386e61998-03-20Fredrik Hübinette (Hubbe) 
10dac82004-04-05Martin Stjernholm  if(FD < 0)
b1c4582003-01-11Martin Nilsson  Pike_error("Stdio.File->lock(): File is not open.\n");
d386e61998-03-20Fredrik Hübinette (Hubbe) 
9f516a2001-12-16Martin Stjernholm  if(!args || UNSAFE_IS_ZERO(Pike_sp-args))
d386e61998-03-20Fredrik Hübinette (Hubbe)  { if(THIS->key #ifdef _REENTRANT
1d456f2003-02-20Henrik Grubbström (Grubba)  && OB2KEY(THIS->key)->owner == Pike_interpreter.thread_state
d386e61998-03-20Fredrik Hübinette (Hubbe) #endif ) {
6abbbb2000-08-27Henrik Grubbström (Grubba)  if (flags & fd_LOCK_NB) {
bce1182000-08-27Henrik Grubbström (Grubba) #ifdef EWOULDBLOCK
ae39322003-09-30Martin Stjernholm  ERRNO = errno = EWOULDBLOCK;
bce1182000-08-27Henrik Grubbström (Grubba) #else /* !EWOULDBLOCK */
ae39322003-09-30Martin Stjernholm  ERRNO = errno = EAGAIN;
bce1182000-08-27Henrik Grubbström (Grubba) #endif /* EWOULDBLOCK */
6abbbb2000-08-27Henrik Grubbström (Grubba)  pop_n_elems(args); push_int(0); return; } else {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Recursive file locks!\n");
6abbbb2000-08-27Henrik Grubbström (Grubba)  }
d386e61998-03-20Fredrik Hübinette (Hubbe)  } } o=clone_object(file_lock_key_program,0);
a1ef721998-04-05Fredrik Hübinette (Hubbe) 
d386e61998-03-20Fredrik Hübinette (Hubbe)  THREADS_ALLOW();
e6f98c1998-05-22David Hedbor #ifdef HAVE_FD_FLOCK
d386e61998-03-20Fredrik Hübinette (Hubbe)  ret=fd_flock(fd, flags);
e6f98c1998-05-22David Hedbor #else ret=fd_lockf(fd, flags);
ee71702000-01-30Per Hedbor #endif
d386e61998-03-20Fredrik Hübinette (Hubbe)  THREADS_DISALLOW(); if(ret<0) { free_object(o); ERRNO=errno; pop_n_elems(args); push_int(0); }else{
bce1182000-08-27Henrik Grubbström (Grubba)  THIS->key = o;
a1ef721998-04-05Fredrik Hübinette (Hubbe)  OB2KEY(o)->f=THIS;
bce1182000-08-27Henrik Grubbström (Grubba)  add_ref(OB2KEY(o)->file = Pike_fp->current_object);
d386e61998-03-20Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_object(o); } }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl Stdio.FileLockKey lock() *! @decl Stdio.FileLockKey lock(int(0..1) is_recursive) *! *! Makes an exclusive file lock on this file. *! *! @seealso *! @[trylock()] */
d386e61998-03-20Fredrik Hübinette (Hubbe) static void file_lock(INT32 args) {
bce1182000-08-27Henrik Grubbström (Grubba)  low_file_lock(args, fd_LOCK_EX);
d386e61998-03-20Fredrik Hübinette (Hubbe) }
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @decl Stdio.FileLockKey trylock() *! @decl Stdio.FileLockKey trylock(int(0..1) is_recursive) *! *! Attempts to place a file lock on this file. *! *! @seealso *! @[lock()] */
3030771998-05-27Fredrik Hübinette (Hubbe) /* If (fd_LOCK_EX | fd_LOCK_NB) is used with lockf, the result will be * F_TEST, which only tests for the existance of a lock on the file. */
10dac82004-04-05Martin Stjernholm #ifdef HAVE_FD_FLOCK
e6f98c1998-05-22David Hedbor static void file_trylock(INT32 args) {
10dac82004-04-05Martin Stjernholm  low_file_lock(args, fd_LOCK_EX | fd_LOCK_NB); } #else static void file_trylock(INT32 args) { low_file_lock(args, fd_LOCK_NB);
914f6d2004-04-04Henrik Grubbström (Grubba) }
10dac82004-04-05Martin Stjernholm #endif
d386e61998-03-20Fredrik Hübinette (Hubbe) 
5923b12000-07-06Fredrik Hübinette (Hubbe) #define THIS_KEY ((struct file_lock_key_storage *)(Pike_fp->current_storage))
74dfe82012-12-30Jonas Walldén static void init_file_lock_key(struct object *UNUSED(o))
d386e61998-03-20Fredrik Hübinette (Hubbe) {
a1ef721998-04-05Fredrik Hübinette (Hubbe)  THIS_KEY->f=0;
d386e61998-03-20Fredrik Hübinette (Hubbe) #ifdef _REENTRANT
1d456f2003-02-20Henrik Grubbström (Grubba)  THIS_KEY->owner=Pike_interpreter.thread_state; add_ref(THIS_KEY->owner_obj=Pike_interpreter.thread_state->thread_obj);
d386e61998-03-20Fredrik Hübinette (Hubbe) #endif }
74dfe82012-12-30Jonas Walldén static void exit_file_lock_key(struct object *DEBUGUSED(o))
d386e61998-03-20Fredrik Hübinette (Hubbe) {
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(THIS_KEY->f)
d386e61998-03-20Fredrik Hübinette (Hubbe)  {
10dac82004-04-05Martin Stjernholm  int fd=THIS_KEY->f->box.fd;
d386e61998-03-20Fredrik Hübinette (Hubbe)  int err;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(THIS_KEY->f->key != o)
5aad932002-08-15Marcus Comstedt  Pike_fatal("File lock key is wrong!\n");
d386e61998-03-20Fredrik Hübinette (Hubbe) #endif do {
00f1d92000-04-14Henrik Grubbström (Grubba)  THREADS_ALLOW();
e6f98c1998-05-22David Hedbor #ifdef HAVE_FD_FLOCK
d386e61998-03-20Fredrik Hübinette (Hubbe)  err=fd_flock(fd, fd_LOCK_UN);
e6f98c1998-05-22David Hedbor #else err=fd_lockf(fd, fd_LOCK_UN); #endif
00f1d92000-04-14Henrik Grubbström (Grubba)  THREADS_DISALLOW(); if ((err < 0) && (errno == EINTR)) { check_threads_etc(); }
d386e61998-03-20Fredrik Hübinette (Hubbe)  }while(err<0 && errno==EINTR); #ifdef _REENTRANT
1d456f2003-02-20Henrik Grubbström (Grubba)  THIS_KEY->owner = NULL; if(THIS_KEY->owner_obj)
d386e61998-03-20Fredrik Hübinette (Hubbe)  {
1d456f2003-02-20Henrik Grubbström (Grubba)  free_object(THIS_KEY->owner_obj); THIS_KEY->owner_obj = NULL;
d386e61998-03-20Fredrik Hübinette (Hubbe)  } #endif
bce1182000-08-27Henrik Grubbström (Grubba)  THIS_KEY->f->key = 0; THIS_KEY->f = 0;
d386e61998-03-20Fredrik Hübinette (Hubbe)  } }
bcb7ab2002-10-04Henrik Grubbström (Grubba) static void init_file_locking(void) { ptrdiff_t off;
e3c6c82003-10-28Martin Stjernholm  START_NEW_PROGRAM_ID (STDIO_FILE_LOCK_KEY);
bcb7ab2002-10-04Henrik Grubbström (Grubba)  off = ADD_STORAGE(struct file_lock_key_storage); #ifdef _REENTRANT
4903e82016-01-30Martin Nilsson  PIKE_MAP_VARIABLE("_owner", off + OFFSETOF(file_lock_key_storage, owner_obj), tObj, PIKE_T_OBJECT, 0);
bcb7ab2002-10-04Henrik Grubbström (Grubba) #endif
4903e82016-01-30Martin Nilsson  PIKE_MAP_VARIABLE("_file", off + OFFSETOF(file_lock_key_storage, file), tObj, PIKE_T_OBJECT, 0);
bcb7ab2002-10-04Henrik Grubbström (Grubba)  set_init_callback(init_file_lock_key); set_exit_callback(exit_file_lock_key); file_lock_key_program=end_program(); file_lock_key_program->flags |= PROGRAM_DESTRUCT_IMMEDIATE; } static void exit_file_locking(void) { if(file_lock_key_program) { free_program(file_lock_key_program); file_lock_key_program=0; } } #else /* !(HAVE_FD_FLOCK || HAVE_FD_LOCKF) */ #define init_file_locking() #define exit_file_locking() #endif /* HAVE_FD_FLOCK || HAVE_FD_LOCKF */
9c052f2001-02-15Henrik Grubbström (Grubba) /*! @endclass */
bcb7ab2002-10-04Henrik Grubbström (Grubba) /*! @decl array(int) get_all_active_fd()
60ab812002-06-27Martin Nilsson  *! Returns the id of all the active file descriptors. */
98a4b32002-06-27Martin Nilsson static void f_get_all_active_fd(INT32 args)
60ab812002-06-27Martin Nilsson {
e16e512014-10-02Per Hedbor  int i,fds=0;
40962a2003-03-27Martin Stjernholm  PIKE_STAT_T foo;
e16e512014-10-02Per Hedbor  struct svalue *sp;
60ab812002-06-27Martin Nilsson  pop_n_elems(args);
e16e512014-10-02Per Hedbor  sp = Pike_sp;
60ab812002-06-27Martin Nilsson  {
e16e512014-10-02Per Hedbor  DIR *tmp;
60ab812002-06-27Martin Nilsson  THREADS_ALLOW();
e16e512014-10-02Per Hedbor #ifndef __NT__ if( (tmp = opendir( #ifdef HAVE_DARWIN_XATTR "/dev/fd" #else "/proc/self/fd" #endif )) )
60ab812002-06-27Martin Nilsson  {
a6cba12014-10-28Henrik Grubbström (Grubba) #ifdef HAVE_DIRFD
e16e512014-10-02Per Hedbor  INT_TYPE dfd = dirfd(tmp);
a6cba12014-10-28Henrik Grubbström (Grubba) #endif
e16e512014-10-02Per Hedbor  while(1) { INT_TYPE fd; char *ep;
f733972017-02-26Henrik Grubbström (Grubba)  struct dirent *res;
e16e512014-10-02Per Hedbor  /* solaris, linux, cygwin, darwin, netbsd et.al. */ res = NULL;
f733972017-02-26Henrik Grubbström (Grubba)  while( UNLIKELY(!(res = readdir(tmp))) && UNLIKELY(errno==EINTR))
e16e512014-10-02Per Hedbor  ; if( !res ) break; fd = strtol(res->d_name, &ep, 10);
a6cba12014-10-28Henrik Grubbström (Grubba)  if( LIKELY(ep != res->d_name) #ifdef HAVE_DIRFD && (fd != dfd) #endif )
e16e512014-10-02Per Hedbor  { SET_SVAL_TYPE_SUBTYPE(*sp,PIKE_T_INT,0); sp++->u.integer = fd; fds++; } } closedir(tmp);
60ab812002-06-27Martin Nilsson  }
e16e512014-10-02Per Hedbor  else #endif /* __NT__ */ { #ifdef HAVE_SYSCONF int max = sysconf(_SC_OPEN_MAX); /* NOTE: This might have been lowered, so we might not actually * get all FD:s. It is usually good, however. * * Also, this is not used on many systems */ #else int max = 65535; #endif for (i=0; i<max; i++) { int q; q = fd_fstat(i,&foo); if(!q) { SET_SVAL_TYPE_SUBTYPE(*sp,PIKE_T_INT,0); sp++->u.integer = i; fds++; } } } THREADS_DISALLOW(); Pike_sp = sp;
60ab812002-06-27Martin Nilsson  } f_aggregate(fds); }
65820a2012-05-02Bill Welliver /*! @decl constant NOTE_ATTRIB = 8 * * Used with @[Stdio.File()->set_fs_event_callback()] to monitor for attribute changes on a file. * * @note * Available on systems that use kqueue. */ /*! @decl constant NOTE_WRITE = 2 * * Used with @[Stdio.File()->set_fs_event_callback()] to monitor for writes to a file. * * @note * Available on systems that use kqueue. */ /*! @decl constant NOTE_DELETE = 1 * * Used with @[Stdio.File()->set_fs_event_callback()] to monitor for deletion of a file. * * @note * Available on systems that use kqueue. */ /*! @decl constant NOTE_EXTEND = 4 * * Used with @[Stdio.File()->set_fs_event_callback()] to monitor for extension events on a file. * * @note * Available on systems that use kqueue. */ /*! @decl constant NOTE_LINK = 16 * * Used with @[Stdio.File()->set_fs_event_callback()] to monitor for changes to a file's link count. * * @note * Available on systems that use kqueue. */ /*! @decl constant NOTE_RENAME = 32 * * Used with @[Stdio.File()->set_fs_event_callback()] to monitor for move or rename events on a file. * * @note * Available on systems that use kqueue. */ /*! @decl constant NOTE_REVOKE = 64 * * Used with @[Stdio.File()->set_fs_event_callback()] to monitor for access revokation (unmount, etc). * * @note * Available on systems that use kqueue. */
89fdb32010-11-19Henrik Grubbström (Grubba) /*! @decl constant PROP_SEND_FD = 64 *!
f126b62010-11-19Henrik Grubbström (Grubba)  *! The @[Stdio.File] object might support the @[Stdio.File()->send_fd()] *! operation.
89fdb32010-11-19Henrik Grubbström (Grubba)  *! *! @seealso
f126b62010-11-19Henrik Grubbström (Grubba)  *! @[Stdio.File()->pipe()], @[Stdio.File()->send_fd()], *! @[Stdio.File()->receive_fd()]
76fd952001-11-25Martin Nilsson  */
89fdb32010-11-19Henrik Grubbström (Grubba) /*! @decl constant PROP_REVERSE = 32 *! Request reversed operation. *! *! Used as argument to @[Stdio.File()->pipe()], when *! @[PROP_BIDIRECTIONAL] hasn't been specified, to *! request the direction of the resulting pipe to *! reversed. *! *! @seealso *! @[Stdio.File()->pipe()]
76fd952001-11-25Martin Nilsson  */
89fdb32010-11-19Henrik Grubbström (Grubba) /*! @decl constant PROP_BIDIRECTIONAL = 16 *! The file is bi-directional. *! *! @seealso *! @[Stdio.File()->pipe()]
76fd952001-11-25Martin Nilsson  */
89fdb32010-11-19Henrik Grubbström (Grubba) /*! @decl constant PROP_BUFFERED = 8 *! The file is buffered (usually 4KB). *! *! @seealso *! @[Stdio.File()->pipe()]
76fd952001-11-25Martin Nilsson  */
89fdb32010-11-19Henrik Grubbström (Grubba) /*! @decl constant PROP_SHUTDOWN = 4 *! The file supports shutting down transmission in either *! direction. *! *! @seealso *! @[Stdio.File()->close()], @[Stdio.File()->pipe()]
9637042003-10-05Henrik Grubbström (Grubba)  */
89fdb32010-11-19Henrik Grubbström (Grubba) /*! @decl constant PROP_NONBLOCK = 2 *! The file supports nonblocking I/O. *! *! @seealso *! @[Stdio.File()->pipe()]
76fd952001-11-25Martin Nilsson  */
89fdb32010-11-19Henrik Grubbström (Grubba) /*! @decl constant PROP_IPC = 1 *! *! The file may be used for inter process communication. *! *! @seealso *! @[Stdio.File()->pipe()]
76fd952001-11-25Martin Nilsson  */
f126b62010-11-19Henrik Grubbström (Grubba) /*! @decl constant __HAVE_SEND_FD__ *! *! Support for sending of file descriptors over *! @[Stdio.File()->pipe()] objects with @[PROP_SEND_FD] *! capability is supported. *! *! @seealso *! @[Stdio.File()->send_fd()], @[Stdio.File()->receive_fd()], *! @[Stdio.File()->read()], @[Stdio.File()->write()], *! @[Stdio.File()->pipe()] */
76fd952001-11-25Martin Nilsson /*! @decl constant __OOB__ *! Implementation level of nonblocking I/O OOB support. *! @int *! @value 0 *! Nonblocking OOB support is not supported. *! @value 1 *! Nonblocking OOB works a little. *! @value 2 *! Nonblocking OOB almost works. *! @value 3 *! Nonblocking OOB works as intended. *! @value -1 *! Unknown level of nonblocking OOB support. *! @endint *! This constant only exists when OOB operations are *! available, i.e. when @[__HAVE_OOB__] is 1. */ /*! @decl constant __HAVE_OOB__
15a3d22003-10-23Henrik Grubbström (Grubba)  *! Exists and has the value 1 if OOB operations are available. *! *! @note *! In Pike 7.5 and later OOB operations are always present.
76fd952001-11-25Martin Nilsson  */
51ef5c2002-10-21Marcus Comstedt PIKE_MODULE_EXIT
5267b71995-08-09Fredrik Hübinette (Hubbe) {
29f9a92013-06-11Martin Nilsson  exit_stdio_efuns(); exit_stdio_stat();
6c638f2000-08-28Henrik Grubbström (Grubba) 
29f9a92013-06-11Martin Nilsson  exit_stdio_udp(); exit_stdio_sendfile();
8cccac2014-08-28Per Hedbor  exit_stdio_buffer();
ae9b441999-04-20Henrik Grubbström (Grubba) 
e4419e1997-02-06Fredrik Hübinette (Hubbe)  if(file_program) { free_program(file_program); file_program=0; }
a1ef721998-04-05Fredrik Hübinette (Hubbe)  if(file_ref_program) { free_program(file_ref_program); file_ref_program=0; }
d386e61998-03-20Fredrik Hübinette (Hubbe)  exit_file_locking();
ef75552010-02-18Stephen R. van den Berg #ifndef HAVE_SOCKETPAIR
c9d4e51999-08-10Henrik Grubbström (Grubba)  if (socketpair_fd >= 0) {
ae39322003-09-30Martin Stjernholm  while (fd_close(socketpair_fd) && errno == EINTR) {}
c9d4e51999-08-10Henrik Grubbström (Grubba)  socketpair_fd = -1; }
ef75552010-02-18Stephen R. van den Berg #endif
29f9a92013-06-11Martin Nilsson  exit_stdio_port();
5267b71995-08-09Fredrik Hübinette (Hubbe) }
e0d7da2011-09-07Henrik Grubbström (Grubba) #define REF (*((struct svalue *)(Pike_fp->current_storage)))
c201101998-03-25Henrik Grubbström (Grubba) 
5b793f2000-04-03Fredrik Hübinette (Hubbe) #define FILE_FUNC(X,Y,Z) \
34a1df2005-04-08Henrik Grubbström (Grubba)  static ptrdiff_t PIKE_CONCAT(Y,_function_number); \ void PIKE_CONCAT(Y,_ref) (INT32 args) { \
e0d7da2011-09-07Henrik Grubbström (Grubba)  struct object *o = REF.u.object; \ int fun = PIKE_CONCAT(Y,_function_number); \ struct program *prog; \
34a1df2005-04-08Henrik Grubbström (Grubba)  debug_malloc_touch(o); \
017b572011-10-28Henrik Grubbström (Grubba)  if(!o || (TYPEOF(REF) != PIKE_T_OBJECT) || !o->prog) { \
34a1df2005-04-08Henrik Grubbström (Grubba)  /* This is a temporary kluge */ \ Pike_error("Stdio.File(): not open.\n"); \ } \
017b572011-10-28Henrik Grubbström (Grubba)  prog = o->prog->inherits[SUBTYPEOF(REF)].prog; \ fun += o->prog->inherits[SUBTYPEOF(REF)].identifier_level; \
e0d7da2011-09-07Henrik Grubbström (Grubba)  if(prog != file_program) \
34a1df2005-04-08Henrik Grubbström (Grubba)  Pike_error("Wrong type of object in Stdio.File->_fd\n"); \
e0d7da2011-09-07Henrik Grubbström (Grubba)  apply_low(o, fun, args); \
34a1df2005-04-08Henrik Grubbström (Grubba)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a1ef721998-04-05Fredrik Hübinette (Hubbe) #include "file_functions.h"
e4419e1997-02-06Fredrik Hübinette (Hubbe) 
74dfe82012-12-30Jonas Walldén static void file___init_ref(struct object *UNUSED(o))
8317a52004-04-06Henrik Grubbström (Grubba) {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(REF, PIKE_T_OBJECT, 0, object, file_make_object_from_fd(-1, 0, 0));
8317a52004-04-06Henrik Grubbström (Grubba) }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
ce3d2f2014-10-01Martin Nilsson void check_static_file_data(struct callback *UNUSED(a), void *UNUSED(b), void *UNUSED(c))
38ac571998-05-19Fredrik Hübinette (Hubbe) { if(file_program) {
34a1df2005-04-08Henrik Grubbström (Grubba) #define FILE_FUNC(X,Y,Z) \ if(PIKE_CONCAT(Y,_function_number)<0 ||