]> Zhao Yanbai Git Server - minix.git/commitdiff
socket: implement SOCK_CLOEXEC and SOCK_NONBLOCK 57/357/4
authorThomas Veerman <thomas@minix3.org>
Mon, 25 Feb 2013 11:36:29 +0000 (11:36 +0000)
committerThomas Veerman <thomas@minix3.org>
Thu, 28 Feb 2013 10:08:53 +0000 (10:08 +0000)
Change-Id: I3fa36fa999c82a192d402cb4d913bd397e106e53

lib/libc/sys-minix/socket.c
servers/vfs/misc.c
servers/vfs/pipe.c
servers/vfs/proto.h
servers/vfs/read.c
servers/vfs/select.c
sys/sys/fcntl.h

index e4e29dc21db299ca80f393ebda460cf79923e93d..cc00596a0c4e298e90ed7be6ccf40ab9e77b8ec3 100644 (file)
@@ -18,12 +18,17 @@ __weak_alias(socket, _socket)
 
 #define DEBUG 0
 
-static int _tcp_socket(int protocol);
-static int _udp_socket(int protocol);
+static int _tcp_socket(int type, int protocol);
+static int _udp_socket(int type, int protocol);
 static int _uds_socket(int type, int protocol);
+static void _socket_flags(int type, int *result);
 
 int socket(int domain, int type, int protocol)
 {
+       int sock_type;
+
+       sock_type = type & ~SOCK_FLAGS_MASK;
+
 #if DEBUG
        fprintf(stderr, "socket: domain %d, type %d, protocol %d\n",
                domain, type, protocol);
@@ -37,15 +42,16 @@ int socket(int domain, int type, int protocol)
                return -1;
        }
 
-       if (domain == AF_UNIX && (type == SOCK_STREAM ||
-                               type == SOCK_DGRAM || type == SOCK_SEQPACKET))
+       if (domain == AF_UNIX && (sock_type == SOCK_STREAM ||
+                                 sock_type == SOCK_DGRAM ||
+                                 sock_type == SOCK_SEQPACKET))
                return _uds_socket(type, protocol);
 
-       if (domain == AF_INET && type == SOCK_STREAM)
-               return _tcp_socket(protocol);
+       if (domain == AF_INET && sock_type == SOCK_STREAM)
+               return _tcp_socket(type, protocol);
 
-       if (domain == AF_INET && type == SOCK_DGRAM)
-               return _udp_socket(protocol);
+       if (domain == AF_INET && sock_type == SOCK_DGRAM)
+               return _udp_socket(type, protocol);
 
 #if DEBUG
        fprintf(stderr, "socket: nothing for domain %d, type %d, protocol %d\n",
@@ -55,9 +61,25 @@ int socket(int domain, int type, int protocol)
        return -1;
 }
 
-static int _tcp_socket(int protocol)
+static void
+_socket_flags(int type, int *result)
+{
+       /* Process socket flags */
+       if (type & SOCK_CLOEXEC) {
+               *result |= O_CLOEXEC;
+       }
+       if (type & SOCK_NONBLOCK) {
+               *result |= O_NONBLOCK;
+       }
+       if (type & SOCK_NOSIGPIPE) {
+               *result |= O_NOSIGPIPE;
+       }
+}
+
+static int _tcp_socket(int type, int protocol)
 {
-       int fd;
+       int flags = O_RDWR;
+
        if (protocol != 0 && protocol != IPPROTO_TCP)
        {
 #if DEBUG
@@ -66,13 +88,15 @@ static int _tcp_socket(int protocol)
                errno= EPROTONOSUPPORT;
                return -1;
        }
-       fd= open(TCP_DEVICE, O_RDWR);
-       return fd;
+
+       _socket_flags(type, &flags);
+
+       return open(TCP_DEVICE, flags);
 }
 
-static int _udp_socket(int protocol)
+static int _udp_socket(int type, int protocol)
 {
-       int r, fd, t_errno;
+       int r, fd, t_errno, flags = O_RDWR;
        struct sockaddr_in sin;
 
        if (protocol != 0 && protocol != IPPROTO_UDP)
@@ -83,7 +107,8 @@ static int _udp_socket(int protocol)
                errno= EPROTONOSUPPORT;
                return -1;
        }
-       fd= open(UDP_DEVICE, O_RDWR);
+       _socket_flags(type, &flags);
+       fd= open(UDP_DEVICE, flags);
        if (fd == -1)
                return fd;
 
@@ -104,7 +129,7 @@ static int _udp_socket(int protocol)
 
 static int _uds_socket(int type, int protocol)
 {
-       int fd, r;
+       int fd, r, flags = O_RDWR, sock_type;
        if (protocol != 0)
        {
 #if DEBUG
@@ -114,7 +139,8 @@ static int _uds_socket(int type, int protocol)
                return -1;
        }
 
-       fd= open(UDS_DEVICE, O_RDWR);
+       _socket_flags(type, &flags);
+       fd= open(UDS_DEVICE, flags);
        if (fd == -1) {
                return fd;
        }
@@ -122,7 +148,8 @@ static int _uds_socket(int type, int protocol)
        /* set the type for the socket via ioctl (SOCK_DGRAM, 
         * SOCK_STREAM, SOCK_SEQPACKET, etc)
         */
-       r= ioctl(fd, NWIOSUDSTYPE, &type);
+       sock_type = type & ~SOCK_FLAGS_MASK;
+       r= ioctl(fd, NWIOSUDSTYPE, &sock_type);
        if (r == -1) {
                int ioctl_errno;
 
index 03de68ca4738efa07e1f6234ba8e5ed189d6ab02..705ba95096448af509347bbfd344d3348faa177e 100644 (file)
@@ -286,7 +286,16 @@ int do_fcntl()
 
        break;
      }
-
+    case F_GETNOSIGPIPE:
+       /* POSIX: return value other than -1 is flag is set, else -1 */
+       r = -1;
+       if (f->filp_flags & O_NOSIGPIPE)
+               r = 0;
+       break;
+    case F_SETNOSIGPIPE:
+       fl = (O_NOSIGPIPE);
+       f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
+       break;
     default:
        r = EINVAL;
   }
index 4a61e7e754bc77c1e9bff90531d0d7f9148235aa..9c7e230a5c64681c96ee95cdf5ce6a61c0e125e9 100644 (file)
@@ -174,7 +174,7 @@ endpoint_t map_to_fs_e;
  *                             pipe_check                                   *
  *===========================================================================*/
 int pipe_check(
-struct vnode *vp,      /* the inode of the pipe */
+struct filp *filp,     /* the filp of the pipe */
 int rw_flag,           /* READING or WRITING */
 int oflags,            /* flags set by open or fcntl */
 int bytes,             /* bytes to be read or written (all chunks) */
@@ -186,9 +186,12 @@ int notouch                /* check only */
  * and there is no writer, return 0 bytes.  If a process is writing to a
  * pipe and no one is reading from it, give a broken pipe error.
  */
+  struct vnode *vp;
   off_t pos;
   int r = OK;
 
+  vp = filp->filp_vno;
+
   /* Reads start at the beginning; writes append to pipes */
   if (notouch) /* In this case we don't actually care whether data transfer
                * would succeed. See POSIX 1003.1-2008 */
@@ -221,10 +224,6 @@ int notouch                /* check only */
 
   /* Process is writing to a pipe. */
   if (find_filp(vp, R_BIT) == NULL) {
-       /* Process is writing, but there is no reader. Tell kernel to generate
-        * a SIGPIPE signal. */
-       if (!notouch) sys_kill(fp->fp_endpoint, SIGPIPE);
-
        return(EPIPE);
   }
 
index b98d7420d52d27a0ad4d44a0d05c2f96fade741f..48865d6cb23fe821b7525731fdff6340c54c8dab 100644 (file)
@@ -186,7 +186,7 @@ int do_check_perms(void);
 int do_pipe(void);
 int map_vnode(struct vnode *vp, endpoint_t fs_e);
 void unpause(endpoint_t proc_e);
-int pipe_check(struct vnode *vp, int rw_flag, int oflags, int bytes,
+int pipe_check(struct filp *filp, int rw_flag, int oflags, int bytes,
        int notouch);
 void release(struct vnode *vp, int op, int count);
 void revive(endpoint_t proc_e, int returned);
index 05f173aa282af42d386e238c92df00e413334d32..90e8c4a72b707bc0881fb9d4dd7eea888916638c 100644 (file)
@@ -124,27 +124,23 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
   register struct vnode *vp;
   u64_t position, res_pos, new_pos;
   unsigned int cum_io, cum_io_incr, res_cum_io;
-  int op, oflags, r;
+  int op, r;
 
   position = f->filp_pos;
-  oflags = f->filp_flags;
   vp = f->filp_vno;
   r = OK;
   cum_io = 0;
 
   if (size > SSIZE_MAX) return(EINVAL);
 
-  if (S_ISFIFO(vp->v_mode)) {
+  op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
+
+  if (S_ISFIFO(vp->v_mode)) {          /* Pipes */
        if (fp->fp_cum_io_partial != 0) {
                panic("VFS: read_write: fp_cum_io_partial not clear");
        }
        r = rw_pipe(rw_flag, for_e, f, buf, size);
-       return(r);
-  }
-
-  op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
-
-  if (S_ISCHR(vp->v_mode)) {   /* Character special files. */
+  } else if (S_ISCHR(vp->v_mode)) {    /* Character special files. */
        dev_t dev;
        int suspend_reopen;
 
@@ -154,7 +150,7 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
        suspend_reopen = (f->filp_state & FS_NEEDS_REOPEN);
        dev = (dev_t) vp->v_sdev;
 
-       r = dev_io(op, dev, for_e, buf, position, size, oflags,
+       r = dev_io(op, dev, for_e, buf, position, size, f->filp_flags,
                   suspend_reopen);
        if (r >= 0) {
                cum_io = r;
@@ -178,7 +174,7 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
   } else {                             /* Regular files */
        if (rw_flag == WRITING) {
                /* Check for O_APPEND flag. */
-               if (oflags & O_APPEND) position = cvul64(vp->v_size);
+               if (f->filp_flags & O_APPEND) position = cvul64(vp->v_size);
        }
 
        /* Issue request */
@@ -208,7 +204,18 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
 
   f->filp_pos = position;
 
-  if (r == OK) return(cum_io);
+  if (r == EPIPE && rw_flag == WRITING) {
+       /* Process is writing, but there is no reader. Tell the kernel to
+        * generate s SIGPIPE signal.
+        */
+       if (!(f->filp_flags & O_NOSIGPIPE)) {
+               sys_kill(fp->fp_endpoint, SIGPIPE);
+       }
+  }
+
+  if (r == OK) {
+       return(cum_io);
+  }
   return(r);
 }
 
@@ -277,7 +284,7 @@ size_t req_size;
   /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
   cum_io = fp->fp_cum_io_partial;
 
-  r = pipe_check(vp, rw_flag, oflags, req_size, 0);
+  r = pipe_check(f, rw_flag, oflags, req_size, 0);
   if (r <= 0) {
        if (r == SUSPEND) pipe_suspend(f, buf, req_size);
        return(r);
index d62f4aa1007def49d39e3a1f5da2103ce1c190c9..bc46430b3399767ddd74c6f1e799b376fa186613 100644 (file)
@@ -453,7 +453,7 @@ static int select_request_pipe(struct filp *f, int *ops, int block)
 
   if ((*ops & (SEL_RD|SEL_ERR))) {
        /* Check if we can read 1 byte */
-       err = pipe_check(f->filp_vno, READING, f->filp_flags & ~O_NONBLOCK, 1,
+       err = pipe_check(f, READING, f->filp_flags & ~O_NONBLOCK, 1,
                         1 /* Check only */);
 
        if (err != SUSPEND)
@@ -470,7 +470,7 @@ static int select_request_pipe(struct filp *f, int *ops, int block)
 
   if ((*ops & (SEL_WR|SEL_ERR))) {
        /* Check if we can write 1 byte */
-       err = pipe_check(f->filp_vno, WRITING, f->filp_flags & ~O_NONBLOCK, 1,
+       err = pipe_check(f, WRITING, f->filp_flags & ~O_NONBLOCK, 1,
                         1 /* Check only */);
 
        if (err != SUSPEND)
index fcfaa9ad59b8d17b290488eeba12d21ca2f526db..15b4a0c2184b67895dd2f4eea782e8e3cbd0f16d 100644 (file)
@@ -73,7 +73,9 @@
                                 * restart
                                 */
 #define O_CLOEXEC     020000   /* close on exec */
-
+#if defined(_NETBSD_SOURCE)
+#define O_NOSIGPIPE   040000   /* don't deliver sigpipe */
+#endif
 
 #ifndef __minix  /* NOT SUPPORTED! */
 #if defined(_NETBSD_SOURCE)
 #define F_SETLK            6   /* set record locking information */
 #define F_SETLKW           7   /* set record locking info; wait if blocked */
 #define F_FREESP           8   /* free a section of a regular file */
+#if defined(_NETBSD_SOURCE)
+#define F_GETNOSIGPIPE     9
+#define F_SETNOSIGPIPE    10
+#endif
 
 /* File descriptor flags used for fcntl().  POSIX Table 6-2. */
 #define FD_CLOEXEC         1   /* close on exec flag for third arg of fcntl */