Merge branch 'dfsg-orig' into dfsg-debian
[debian/tar] / gnu / fcntl.c
index 3f4af8a2ae8bb26836a63cfa26e1966264df6919..23b73e975c844d976a032d2582f482fac0f43f33 100644 (file)
@@ -1,8 +1,6 @@
-/* -*- buffer-read-only: t -*- vi: set ro: */
-/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
 /* Provide file descriptor control.
 
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2009-2015 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
 #undef fcntl
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-/* Get declarations of the Win32 API functions.  */
+/* Get declarations of the native Windows API functions.  */
 # define WIN32_LEAN_AND_MEAN
 # include <windows.h>
 
+/* Get _get_osfhandle.  */
+# include "msvc-nothrow.h"
+
 /* Upper bound on getdtablesize().  See lib/getdtablesize.c.  */
 # define OPEN_MAX_MAX 0x10000
 
@@ -88,16 +89,32 @@ 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;
         }
-      duplicated_fd = _open_osfhandle ((long) new_handle, flags);
+      duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags);
       if (duplicated_fd < 0)
         {
           CloseHandle (new_handle);
-          errno = EMFILE;
           result = -1;
           break;
         }
@@ -189,7 +206,21 @@ rpl_fcntl (int fd, int action, /* arg */...)
           errno = EINVAL;
         else
           {
+            /* Haiku alpha 2 loses fd flags on original.  */
+            int flags = fcntl (fd, F_GETFD);
+            if (flags < 0)
+              {
+                result = -1;
+                break;
+              }
             result = fcntl (fd, action, target);
+            if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
+              {
+                int saved_errno = errno;
+                close (result);
+                result = -1;
+                errno = saved_errno;
+              }
 # if REPLACE_FCHDIR
             if (0 <= result)
               result = _gl_register_dup (fd, result);