master
 1#define _GNU_SOURCE
 2#include <fcntl.h>
 3#include <stdarg.h>
 4#include <errno.h>
 5#include "syscall.h"
 6
 7int 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}