xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/fcntl.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "lib.h"
2 #include <unistd.h>
3 #include <errno.h>
4 #include <stdarg.h>
5 #include "sys9.h"
6 
7 /*
8  * BUG: advisory locking not implemented
9  */
10 
11 #define OFL (O_ACCMODE|O_NONBLOCK|O_APPEND)
12 
13 int
fcntl(int fd,int cmd,...)14 fcntl(int fd, int cmd, ...)
15 {
16 	int arg, i, ans, err;
17 	Fdinfo *fi, *fans;
18 	va_list va;
19 	unsigned long oflags;
20 
21 	err = 0;
22 	ans = 0;
23 	va_start(va, cmd);
24 	arg = va_arg(va, int);
25 	va_end(va);
26 	fi = &_fdinfo[fd];
27 	if(fd<0 || fd>=OPEN_MAX || !(fi->flags&FD_ISOPEN))
28 		err = EBADF;
29 	else switch(cmd){
30 		case F_DUPFD:
31 			if(fi->flags&(FD_BUFFERED|FD_BUFFEREDX)){
32 				err = EGREG;	/* dup of buffered fd not implemented */
33 				break;
34 			}
35 			oflags = fi->oflags;
36 			for(i = (arg>0)? arg : 0; i<OPEN_MAX; i++)
37 				if(!(_fdinfo[i].flags&FD_ISOPEN))
38 					break;
39 			if(i == OPEN_MAX)
40 				err = EMFILE;
41 			else {
42 				ans = _DUP(fd, i);
43 				if(ans != i){
44 					if(ans < 0){
45 						_syserrno();
46 						err = errno;
47 					}else
48 						err = EBADF;
49 				}else{
50 					fans = &_fdinfo[ans];
51 					fans->flags = fi->flags&~FD_CLOEXEC;
52 					fans->oflags = oflags;
53 					fans->uid = fi->uid;
54 					fans->gid = fi->gid;
55 				}
56 			}
57 			break;
58 		case F_GETFD:
59 			ans = fi->flags&FD_CLOEXEC;
60 			break;
61 		case F_SETFD:
62 			fi->flags = (fi->flags&~FD_CLOEXEC)|(arg&FD_CLOEXEC);
63 			break;
64 		case F_GETFL:
65 			ans = fi->oflags&OFL;
66 			break;
67 		case F_SETFL:
68 			fi->oflags = (fi->oflags&~OFL)|(arg&OFL);
69 			break;
70 		case F_GETLK:
71 		case F_SETLK:
72 		case F_SETLKW:
73 			err = EINVAL;
74 			break;
75 		}
76 	if(err){
77 		errno = err;
78 		ans = -1;
79 	}
80 	return ans;
81 }
82