github.com/afumu/libc@v0.0.6/musl/src/fcntl/fcntl.c (about)

     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  }