xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/fcntl.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "lib.h"
23e12c5d1SDavid du Colombier #include <unistd.h>
33e12c5d1SDavid du Colombier #include <errno.h>
43e12c5d1SDavid du Colombier #include <stdarg.h>
53e12c5d1SDavid du Colombier #include "sys9.h"
63e12c5d1SDavid du Colombier 
73e12c5d1SDavid du Colombier /*
83e12c5d1SDavid du Colombier  * BUG: advisory locking not implemented
93e12c5d1SDavid du Colombier  */
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier #define OFL (O_ACCMODE|O_NONBLOCK|O_APPEND)
123e12c5d1SDavid du Colombier 
133e12c5d1SDavid du Colombier int
fcntl(int fd,int cmd,...)143e12c5d1SDavid du Colombier fcntl(int fd, int cmd, ...)
153e12c5d1SDavid du Colombier {
163e12c5d1SDavid du Colombier 	int arg, i, ans, err;
17*219b2ee8SDavid du Colombier 	Fdinfo *fi, *fans;
183e12c5d1SDavid du Colombier 	va_list va;
193e12c5d1SDavid du Colombier 	unsigned long oflags;
203e12c5d1SDavid du Colombier 
213e12c5d1SDavid du Colombier 	err = 0;
223e12c5d1SDavid du Colombier 	ans = 0;
233e12c5d1SDavid du Colombier 	va_start(va, cmd);
243e12c5d1SDavid du Colombier 	arg = va_arg(va, int);
253e12c5d1SDavid du Colombier 	va_end(va);
263e12c5d1SDavid du Colombier 	fi = &_fdinfo[fd];
273e12c5d1SDavid du Colombier 	if(fd<0 || fd>=OPEN_MAX || !(fi->flags&FD_ISOPEN))
283e12c5d1SDavid du Colombier 		err = EBADF;
293e12c5d1SDavid du Colombier 	else switch(cmd){
303e12c5d1SDavid du Colombier 		case F_DUPFD:
31*219b2ee8SDavid du Colombier 			if(fi->flags&(FD_BUFFERED|FD_BUFFEREDX)){
32*219b2ee8SDavid du Colombier 				err = EGREG;	/* dup of buffered fd not implemented */
33*219b2ee8SDavid du Colombier 				break;
34*219b2ee8SDavid du Colombier 			}
353e12c5d1SDavid du Colombier 			oflags = fi->oflags;
363e12c5d1SDavid du Colombier 			for(i = (arg>0)? arg : 0; i<OPEN_MAX; i++)
373e12c5d1SDavid du Colombier 				if(!(_fdinfo[i].flags&FD_ISOPEN))
383e12c5d1SDavid du Colombier 					break;
393e12c5d1SDavid du Colombier 			if(i == OPEN_MAX)
403e12c5d1SDavid du Colombier 				err = EMFILE;
413e12c5d1SDavid du Colombier 			else {
423e12c5d1SDavid du Colombier 				ans = _DUP(fd, i);
433e12c5d1SDavid du Colombier 				if(ans != i){
443e12c5d1SDavid du Colombier 					if(ans < 0){
453e12c5d1SDavid du Colombier 						_syserrno();
463e12c5d1SDavid du Colombier 						err = errno;
473e12c5d1SDavid du Colombier 					}else
483e12c5d1SDavid du Colombier 						err = EBADF;
493e12c5d1SDavid du Colombier 				}else{
50*219b2ee8SDavid du Colombier 					fans = &_fdinfo[ans];
51*219b2ee8SDavid du Colombier 					fans->flags = fi->flags&~FD_CLOEXEC;
52*219b2ee8SDavid du Colombier 					fans->oflags = oflags;
53*219b2ee8SDavid du Colombier 					fans->uid = fi->uid;
54*219b2ee8SDavid du Colombier 					fans->gid = fi->gid;
553e12c5d1SDavid du Colombier 				}
563e12c5d1SDavid du Colombier 			}
573e12c5d1SDavid du Colombier 			break;
583e12c5d1SDavid du Colombier 		case F_GETFD:
593e12c5d1SDavid du Colombier 			ans = fi->flags&FD_CLOEXEC;
603e12c5d1SDavid du Colombier 			break;
613e12c5d1SDavid du Colombier 		case F_SETFD:
623e12c5d1SDavid du Colombier 			fi->flags = (fi->flags&~FD_CLOEXEC)|(arg&FD_CLOEXEC);
633e12c5d1SDavid du Colombier 			break;
643e12c5d1SDavid du Colombier 		case F_GETFL:
653e12c5d1SDavid du Colombier 			ans = fi->oflags&OFL;
663e12c5d1SDavid du Colombier 			break;
673e12c5d1SDavid du Colombier 		case F_SETFL:
683e12c5d1SDavid du Colombier 			fi->oflags = (fi->oflags&~OFL)|(arg&OFL);
693e12c5d1SDavid du Colombier 			break;
703e12c5d1SDavid du Colombier 		case F_GETLK:
713e12c5d1SDavid du Colombier 		case F_SETLK:
723e12c5d1SDavid du Colombier 		case F_SETLKW:
733e12c5d1SDavid du Colombier 			err = EINVAL;
743e12c5d1SDavid du Colombier 			break;
753e12c5d1SDavid du Colombier 		}
763e12c5d1SDavid du Colombier 	if(err){
773e12c5d1SDavid du Colombier 		errno = err;
783e12c5d1SDavid du Colombier 		ans = -1;
793e12c5d1SDavid du Colombier 	}
803e12c5d1SDavid du Colombier 	return ans;
813e12c5d1SDavid du Colombier }
82