1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1990-1996 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/syscall.h> 30 #include <sys/fcntl.h> 31 #include <sys/errno.h> 32 #include <sys/filio.h> 33 #include <sys/ioccom.h> 34 #include <unistd.h> 35 36 /* The following is an array of fcntl commands. The numbers listed 37 * below are from SVR4. Array is indexed with SunOS 4.1 numbers to 38 * obtain the SVR4 numbers. 39 */ 40 int cmd_op[14] = {0, 1, 2, 3, 4, 23, 24, 14, 6, 7, 21, 20, -1, 22}; 41 42 /* SVR4/SunOS 5.0 equivalent modes */ 43 #define N_O_NDELAY 0x04 44 #define N_O_SYNC 0x10 45 #define N_O_NONBLOCK 0x80 46 #define N_O_CREAT 0x100 47 #define N_O_TRUNC 0x200 48 #define N_O_EXCL 0x400 49 50 #define S5_FASYNC 0x1000 51 52 /* from SVR4 stropts.h */ 53 #define S5_S_RDNORM 0x0040 54 #define S5_S_WRNORM 0x0004 55 #define S5_S_RDBAND 0x0080 56 #define S5_S_BANDURG 0x0200 57 #define S5_I_SETSIG (('S'<<8)|011) 58 #define S5_I_GETSIG (('S'<<8)|012) 59 60 /* Mask corresponding to the bits above in SunOS 4.x */ 61 #define FLAGS_MASK (O_SYNC|O_NONBLOCK|O_CREAT|O_TRUNC|O_EXCL \ 62 |O_NDELAY|FASYNC) 63 #define N_FLAGS_MASK (N_O_NDELAY|N_O_SYNC|N_O_NONBLOCK|N_O_CREAT \ 64 |N_O_TRUNC|N_O_EXCL|S5_FASYNC) 65 66 struct n_flock { 67 short l_type; 68 short l_whence; 69 long l_start; 70 long l_len; /* len == 0 means until end of file */ 71 long l_sysid; 72 long l_pid; 73 long pad[4]; /* reserve area */ 74 } ; 75 76 int fcntl(fd, cmd, arg) 77 int fd, cmd, arg; 78 { 79 return(bc_fcntl(fd, cmd, arg)); 80 } 81 82 int bc_fcntl(fd, cmd, arg) 83 int fd, cmd, arg; 84 { 85 int fds, ret; 86 struct flock *savarg; 87 struct n_flock nfl; 88 extern int errno; 89 int narg, i; 90 91 if ((cmd == F_SETOWN) || (cmd == F_GETOWN)) { 92 ret = _s_fcntl(fd, cmd_op[cmd], arg); 93 if ((ret != -1) || (errno != EINVAL)) 94 return (ret); 95 else { 96 if (cmd == F_GETOWN) { 97 if (_ioctl(fd, S5_I_GETSIG, &i) < 0) { 98 if (errno == EINVAL) 99 i = 0; 100 else 101 return (-1); 102 } 103 if (i & (S5_S_RDBAND|S5_S_BANDURG| 104 S5_S_RDNORM|S5_S_WRNORM)) 105 return (getpid()); 106 return (0); 107 } else { /* cmd == F_SETOWN */ 108 i = S5_S_RDNORM|S5_S_WRNORM|S5_S_RDBAND|S5_S_BANDURG; 109 return (ioctl(fd, S5_I_SETSIG, i)); 110 } 111 } 112 } 113 if (cmd == F_SETFL) { 114 if (arg & FLAGS_MASK) { 115 narg = arg & ~FLAGS_MASK; 116 if (arg & FASYNC) 117 narg |= S5_FASYNC; 118 if (arg & O_SYNC) 119 narg |= N_O_SYNC; 120 if (arg & O_CREAT) 121 narg |= N_O_CREAT; 122 if (arg & O_TRUNC) 123 narg |= N_O_TRUNC; 124 if (arg & O_EXCL) 125 narg |= N_O_EXCL; 126 if (arg & (O_NDELAY)) 127 narg |= N_O_NDELAY; 128 if (arg & O_NONBLOCK) 129 narg |= N_O_NONBLOCK; 130 arg = narg; 131 } 132 } else if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK) { 133 if (arg == 0 || arg == -1) { 134 errno = EFAULT; 135 return(-1); 136 } 137 savarg = (struct flock *)arg; 138 arg = (int) &nfl; 139 nfl.l_type = savarg->l_type; 140 nfl.l_whence = savarg->l_whence; 141 nfl.l_start = savarg->l_start; 142 nfl.l_len = savarg->l_len; 143 nfl.l_pid = savarg->l_pid; 144 } 145 146 ret = _s_fcntl(fd, cmd_op[cmd], arg); 147 148 if (ret != -1) { 149 if (cmd == F_DUPFD) { 150 if ((fds = fd_get(fd)) != -1) 151 fd_add(ret, fds); 152 } else if (cmd == F_GETFL) { 153 if (ret & N_FLAGS_MASK) { 154 narg = ret & ~N_FLAGS_MASK; 155 if (ret & S5_FASYNC) 156 narg |= FASYNC; 157 if (ret & N_O_SYNC) 158 narg |= O_SYNC; 159 if (ret & N_O_NONBLOCK) 160 narg |= O_NONBLOCK; 161 if (ret & N_O_CREAT) 162 narg |= O_CREAT; 163 if (ret & N_O_TRUNC) 164 narg |= O_TRUNC; 165 if (ret & N_O_EXCL) 166 narg |= O_EXCL; 167 if (ret & (N_O_NDELAY)) 168 narg |= O_NDELAY; 169 ret = narg; 170 } 171 } else if (cmd == F_SETLK || cmd == F_SETLKW || 172 cmd == F_GETLK) { 173 savarg->l_type = nfl.l_type; 174 savarg->l_whence = nfl.l_whence; 175 savarg->l_start = nfl.l_start; 176 savarg->l_len = nfl.l_len; 177 savarg->l_pid = nfl.l_pid; 178 } 179 } 180 return(ret); 181 } 182