fcntl.c raw

   1  #define _GNU_SOURCE
   2  #include <fcntl.h>
   3  #include <stdarg.h>
   4  #include <errno.h>
   5  #include "syscall.h"
   6  
   7  int fcntl(int fd, int cmd, ...)
   8  {
   9  	unsigned long arg;
  10  	va_list ap;
  11  	va_start(ap, cmd);
  12  	arg = va_arg(ap, unsigned long);
  13  	va_end(ap);
  14  	if (cmd == F_SETFL) arg |= O_LARGEFILE;
  15  	if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, (void *)arg);
  16  	if (cmd == F_GETOWN) {
  17  		struct f_owner_ex ex;
  18  		int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex);
  19  		if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, (void *)arg);
  20  		if (ret) return __syscall_ret(ret);
  21  		return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid;
  22  	}
  23  	if (cmd == F_DUPFD_CLOEXEC) {
  24  		int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg);
  25  		if (ret != -EINVAL) {
  26  			if (ret >= 0)
  27  				__syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
  28  			return __syscall_ret(ret);
  29  		}
  30  		ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0);
  31  		if (ret != -EINVAL) {
  32  			if (ret >= 0) __syscall(SYS_close, ret);
  33  			return __syscall_ret(-EINVAL);
  34  		}
  35  		ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg);
  36  		if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
  37  		return __syscall_ret(ret);
  38  	}
  39  	switch (cmd) {
  40  	case F_SETLK:
  41  	case F_GETLK:
  42  	case F_GETOWN_EX:
  43  	case F_SETOWN_EX:
  44  		return syscall(SYS_fcntl, fd, cmd, (void *)arg);
  45  	default:
  46  		return syscall(SYS_fcntl, fd, cmd, arg);
  47  	}
  48  }
  49