X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=lib%2Ffcntl.c;h=fd17e962f8bb9671c5e18ac60696d3583ec0edba;hb=978bac5333774bc6e3191772abdc2b9be98aacca;hp=735fa66f4d76484b2a3177c9f7f56ff61d95542d;hpb=d738e90e8360e101b94fca8c79147f59565f62d8;p=debian%2Fgzip diff --git a/lib/fcntl.c b/lib/fcntl.c index 735fa66..fd17e96 100644 --- a/lib/fcntl.c +++ b/lib/fcntl.c @@ -1,6 +1,6 @@ /* Provide file descriptor control. - Copyright (C) 2009-2013 Free Software Foundation, Inc. + Copyright (C) 2009-2016 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -89,8 +89,25 @@ dupfd (int oldfd, int newfd, int flags) inherit, /* InheritHandle */ DUPLICATE_SAME_ACCESS)) /* Options */ { - /* TODO: Translate GetLastError () into errno. */ - errno = EMFILE; + switch (GetLastError ()) + { + case ERROR_TOO_MANY_OPEN_FILES: + errno = EMFILE; + break; + case ERROR_INVALID_HANDLE: + case ERROR_INVALID_TARGET_HANDLE: + case ERROR_DIRECT_ACCESS_HANDLE: + errno = EBADF; + break; + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_INVALID_ACCESS: + errno = EINVAL; + break; + default: + errno = EACCES; + break; + } result = -1; break; } @@ -98,7 +115,6 @@ dupfd (int oldfd, int newfd, int flags) if (duplicated_fd < 0) { CloseHandle (new_handle); - errno = EMFILE; result = -1; break; } @@ -146,6 +162,93 @@ dupfd (int oldfd, int newfd, int flags) } #endif /* W32 */ +#ifdef __KLIBC__ + +# define INCL_DOS +# include + +static int +klibc_fcntl (int fd, int action, /* arg */...) +{ + va_list arg_ptr; + int arg; + struct stat sbuf; + int result = -1; + + va_start (arg_ptr, action); + arg = va_arg (arg_ptr, int); + result = fcntl (fd, action, arg); + /* EPERM for F_DUPFD, ENOTSUP for others */ + if (result == -1 && (errno == EPERM || errno == ENOTSUP) + && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + { + ULONG ulMode; + + switch (action) + { + case F_DUPFD: + /* Find available fd */ + while (fcntl (arg, F_GETFL) != -1 || errno != EBADF) + arg++; + + result = dup2 (fd, arg); + break; + + /* Using underlying APIs is right ? */ + case F_GETFD: + if (DosQueryFHState (fd, &ulMode)) + break; + + result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0; + break; + + case F_SETFD: + if (arg & ~FD_CLOEXEC) + break; + + if (DosQueryFHState (fd, &ulMode)) + break; + + if (arg & FD_CLOEXEC) + ulMode |= OPEN_FLAGS_NOINHERIT; + else + ulMode &= ~OPEN_FLAGS_NOINHERIT; + + /* Filter supported flags. */ + ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR + | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); + + if (DosSetFHState (fd, ulMode)) + break; + + result = 0; + break; + + case F_GETFL: + result = 0; + break; + + case F_SETFL: + if (arg != 0) + break; + + result = 0; + break; + + default : + errno = EINVAL; + break; + } + } + + va_end (arg_ptr); + + return result; +} + +# define fcntl klibc_fcntl +#endif + /* Perform the specified ACTION on the file descriptor FD, possibly using the argument ARG further described below. This replacement handles the following actions, and forwards all others on to the