This source file includes following definitions.
- dupfd
 
- rpl_fcntl_DUPFD
 
- rpl_fcntl_DUPFD_CLOEXEC
 
- klibc_fcntl
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 #include <config.h>
  21 
  22 
  23 #include <fcntl.h>
  24 
  25 #include <errno.h>
  26 #include <limits.h>
  27 #include <stdarg.h>
  28 #include <stdlib.h>
  29 #include <unistd.h>
  30 
  31 #ifdef __KLIBC__
  32 # define INCL_DOS
  33 # include <os2.h>
  34 #endif
  35 
  36 #if defined _WIN32 && ! defined __CYGWIN__
  37 
  38 # define WIN32_LEAN_AND_MEAN
  39 # include <windows.h>
  40 
  41 
  42 # if GNULIB_MSVC_NOTHROW
  43 #  include "msvc-nothrow.h"
  44 # else
  45 #  include <io.h>
  46 # endif
  47 
  48 
  49 # define OPEN_MAX_MAX 0x10000
  50 
  51 
  52 
  53 
  54 static int
  55 dupfd (int oldfd, int newfd, int flags)
     
  56 {
  57   
  58 
  59   HANDLE curr_process = GetCurrentProcess ();
  60   HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd);
  61   unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
  62   unsigned int fds_to_close_bound = 0;
  63   int result;
  64   BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
  65   int mode;
  66 
  67   if (newfd < 0 || getdtablesize () <= newfd)
  68     {
  69       errno = EINVAL;
  70       return -1;
  71     }
  72   if (old_handle == INVALID_HANDLE_VALUE
  73       || (mode = _setmode (oldfd, O_BINARY)) == -1)
  74     {
  75       
  76 
  77       errno = EBADF;
  78       return -1;
  79     }
  80   _setmode (oldfd, mode);
  81   flags |= mode;
  82 
  83   for (;;)
  84     {
  85       HANDLE new_handle;
  86       int duplicated_fd;
  87       unsigned int index;
  88 
  89       if (!DuplicateHandle (curr_process,           
  90                             old_handle,             
  91                             curr_process,           
  92                             (PHANDLE) &new_handle,  
  93                             (DWORD) 0,              
  94                             inherit,                
  95                             DUPLICATE_SAME_ACCESS)) 
  96         {
  97           switch (GetLastError ())
  98             {
  99               case ERROR_TOO_MANY_OPEN_FILES:
 100                 errno = EMFILE;
 101                 break;
 102               case ERROR_INVALID_HANDLE:
 103               case ERROR_INVALID_TARGET_HANDLE:
 104               case ERROR_DIRECT_ACCESS_HANDLE:
 105                 errno = EBADF;
 106                 break;
 107               case ERROR_INVALID_PARAMETER:
 108               case ERROR_INVALID_FUNCTION:
 109               case ERROR_INVALID_ACCESS:
 110                 errno = EINVAL;
 111                 break;
 112               default:
 113                 errno = EACCES;
 114                 break;
 115             }
 116           result = -1;
 117           break;
 118         }
 119       duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags);
 120       if (duplicated_fd < 0)
 121         {
 122           CloseHandle (new_handle);
 123           result = -1;
 124           break;
 125         }
 126       if (newfd <= duplicated_fd)
 127         {
 128           result = duplicated_fd;
 129           break;
 130         }
 131 
 132       
 133       index = (unsigned int) duplicated_fd / CHAR_BIT;
 134       if (fds_to_close_bound <= index)
 135         {
 136           if (sizeof fds_to_close <= index)
 137             
 138             abort ();
 139           memset (fds_to_close + fds_to_close_bound, '\0',
 140                   index + 1 - fds_to_close_bound);
 141           fds_to_close_bound = index + 1;
 142         }
 143       fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT);
 144     }
 145 
 146   
 147   {
 148     int saved_errno = errno;
 149     unsigned int duplicated_fd;
 150 
 151     for (duplicated_fd = 0;
 152          duplicated_fd < fds_to_close_bound * CHAR_BIT;
 153          duplicated_fd++)
 154       if ((fds_to_close[duplicated_fd / CHAR_BIT]
 155            >> (duplicated_fd % CHAR_BIT))
 156           & 1)
 157         close (duplicated_fd);
 158 
 159     errno = saved_errno;
 160   }
 161 
 162 # if REPLACE_FCHDIR
 163   if (0 <= result)
 164     result = _gl_register_dup (oldfd, result);
 165 # endif
 166   return result;
 167 }
 168 #endif 
 169 
 170 
 171 
 172 
 173 static int rpl_fcntl_DUPFD (int fd, int target);
 174 
 175 static int rpl_fcntl_DUPFD_CLOEXEC (int fd, int target);
 176 #ifdef __KLIBC__
 177 
 178 static int klibc_fcntl (int fd, int action, ...);
 179 #endif
 180 
 181 
 182 
 183 
 184 
 185 
 186 
 187 
 188 
 189 
 190 
 191 
 192 
 193 
 194 
 195 
 196 
 197 
 198 
 199 
 200 
 201 int
 202 fcntl (int fd, int action, ...)
 203 #undef fcntl
 204 #ifdef __KLIBC__
 205 # define fcntl klibc_fcntl
 206 #endif
 207 {
 208   va_list arg;
 209   int result = -1;
 210   va_start (arg, action);
 211   switch (action)
 212     {
 213     case F_DUPFD:
 214       {
 215         int target = va_arg (arg, int);
 216         result = rpl_fcntl_DUPFD (fd, target);
 217         break;
 218       }
 219 
 220     case F_DUPFD_CLOEXEC:
 221       {
 222         int target = va_arg (arg, int);
 223         result = rpl_fcntl_DUPFD_CLOEXEC (fd, target);
 224         break;
 225       }
 226 
 227 #if !HAVE_FCNTL
 228     case F_GETFD:
 229       {
 230 # if defined _WIN32 && ! defined __CYGWIN__
 231         HANDLE handle = (HANDLE) _get_osfhandle (fd);
 232         DWORD flags;
 233         if (handle == INVALID_HANDLE_VALUE
 234             || GetHandleInformation (handle, &flags) == 0)
 235           errno = EBADF;
 236         else
 237           result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
 238 # else 
 239         
 240 
 241         if (0 <= dup2 (fd, fd))
 242           result = 0;
 243 # endif 
 244         break;
 245       } 
 246 #endif 
 247 
 248       
 249 
 250 
 251 
 252 
 253 
 254 
 255 
 256     default:
 257       {
 258 #if HAVE_FCNTL
 259         switch (action)
 260           {
 261           #ifdef F_BARRIERFSYNC                  
 262           case F_BARRIERFSYNC:
 263           #endif
 264           #ifdef F_CHKCLEAN                      
 265           case F_CHKCLEAN:
 266           #endif
 267           #ifdef F_CLOSEM                        
 268           case F_CLOSEM:
 269           #endif
 270           #ifdef F_FLUSH_DATA                    
 271           case F_FLUSH_DATA:
 272           #endif
 273           #ifdef F_FREEZE_FS                     
 274           case F_FREEZE_FS:
 275           #endif
 276           #ifdef F_FULLFSYNC                     
 277           case F_FULLFSYNC:
 278           #endif
 279           #ifdef F_GETCONFINED                   
 280           case F_GETCONFINED:
 281           #endif
 282           #ifdef F_GETDEFAULTPROTLEVEL           
 283           case F_GETDEFAULTPROTLEVEL:
 284           #endif
 285           #ifdef F_GETFD                         
 286           case F_GETFD:
 287           #endif
 288           #ifdef F_GETFL                         
 289           case F_GETFL:
 290           #endif
 291           #ifdef F_GETLEASE                      
 292           case F_GETLEASE:
 293           #endif
 294           #ifdef F_GETNOSIGPIPE                  
 295           case F_GETNOSIGPIPE:
 296           #endif
 297           #ifdef F_GETOWN                        
 298           case F_GETOWN:
 299           #endif
 300           #ifdef F_GETPIPE_SZ                    
 301           case F_GETPIPE_SZ:
 302           #endif
 303           #ifdef F_GETPROTECTIONCLASS            
 304           case F_GETPROTECTIONCLASS:
 305           #endif
 306           #ifdef F_GETPROTECTIONLEVEL            
 307           case F_GETPROTECTIONLEVEL:
 308           #endif
 309           #ifdef F_GET_SEALS                     
 310           case F_GET_SEALS:
 311           #endif
 312           #ifdef F_GETSIG                        
 313           case F_GETSIG:
 314           #endif
 315           #ifdef F_MAXFD                         
 316           case F_MAXFD:
 317           #endif
 318           #ifdef F_RECYCLE                       
 319           case F_RECYCLE:
 320           #endif
 321           #ifdef F_SETFIFOENH                    
 322           case F_SETFIFOENH:
 323           #endif
 324           #ifdef F_THAW_FS                       
 325           case F_THAW_FS:
 326           #endif
 327             
 328             result = fcntl (fd, action);
 329             break;
 330 
 331           #ifdef F_ADD_SEALS                     
 332           case F_ADD_SEALS:
 333           #endif
 334           #ifdef F_BADFD                         
 335           case F_BADFD:
 336           #endif
 337           #ifdef F_CHECK_OPENEVT                 
 338           case F_CHECK_OPENEVT:
 339           #endif
 340           #ifdef F_DUP2FD                        
 341           case F_DUP2FD:
 342           #endif
 343           #ifdef F_DUP2FD_CLOEXEC                
 344           case F_DUP2FD_CLOEXEC:
 345           #endif
 346           #ifdef F_DUP2FD_CLOFORK                
 347           case F_DUP2FD_CLOFORK:
 348           #endif
 349           #ifdef F_DUPFD                         
 350           case F_DUPFD:
 351           #endif
 352           #ifdef F_DUPFD_CLOEXEC                 
 353           case F_DUPFD_CLOEXEC:
 354           #endif
 355           #ifdef F_DUPFD_CLOFORK                 
 356           case F_DUPFD_CLOFORK:
 357           #endif
 358           #ifdef F_GETXFL                        
 359           case F_GETXFL:
 360           #endif
 361           #ifdef F_GLOBAL_NOCACHE                
 362           case F_GLOBAL_NOCACHE:
 363           #endif
 364           #ifdef F_MAKECOMPRESSED                
 365           case F_MAKECOMPRESSED:
 366           #endif
 367           #ifdef F_MOVEDATAEXTENTS               
 368           case F_MOVEDATAEXTENTS:
 369           #endif
 370           #ifdef F_NOCACHE                       
 371           case F_NOCACHE:
 372           #endif
 373           #ifdef F_NODIRECT                      
 374           case F_NODIRECT:
 375           #endif
 376           #ifdef F_NOTIFY                        
 377           case F_NOTIFY:
 378           #endif
 379           #ifdef F_OPLKACK                       
 380           case F_OPLKACK:
 381           #endif
 382           #ifdef F_OPLKREG                       
 383           case F_OPLKREG:
 384           #endif
 385           #ifdef F_RDAHEAD                       
 386           case F_RDAHEAD:
 387           #endif
 388           #ifdef F_SETBACKINGSTORE               
 389           case F_SETBACKINGSTORE:
 390           #endif
 391           #ifdef F_SETCONFINED                   
 392           case F_SETCONFINED:
 393           #endif
 394           #ifdef F_SETFD                         
 395           case F_SETFD:
 396           #endif
 397           #ifdef F_SETFL                         
 398           case F_SETFL:
 399           #endif
 400           #ifdef F_SETLEASE                      
 401           case F_SETLEASE:
 402           #endif
 403           #ifdef F_SETNOSIGPIPE                  
 404           case F_SETNOSIGPIPE:
 405           #endif
 406           #ifdef F_SETOWN                        
 407           case F_SETOWN:
 408           #endif
 409           #ifdef F_SETPIPE_SZ                    
 410           case F_SETPIPE_SZ:
 411           #endif
 412           #ifdef F_SETPROTECTIONCLASS            
 413           case F_SETPROTECTIONCLASS:
 414           #endif
 415           #ifdef F_SETSIG                        
 416           case F_SETSIG:
 417           #endif
 418           #ifdef F_SINGLE_WRITER                 
 419           case F_SINGLE_WRITER:
 420           #endif
 421             
 422             {
 423               int x = va_arg (arg, int);
 424               result = fcntl (fd, action, x);
 425             }
 426             break;
 427 
 428           default:
 429             
 430             {
 431               void *p = va_arg (arg, void *);
 432               result = fcntl (fd, action, p);
 433             }
 434             break;
 435           }
 436 #else
 437         errno = EINVAL;
 438 #endif
 439         break;
 440       }
 441     }
 442   va_end (arg);
 443   return result;
 444 }
 445 
 446 static int
 447 rpl_fcntl_DUPFD (int fd, int target)
     
 448 {
 449   int result;
 450 #if !HAVE_FCNTL
 451   result = dupfd (fd, target, 0);
 452 #elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
 453   
 454   if (target < 0 || getdtablesize () <= target)
 455     {
 456       result = -1;
 457       errno = EINVAL;
 458     }
 459   else
 460     {
 461       
 462       int flags = fcntl (fd, F_GETFD);
 463       if (flags < 0)
 464         result = -1;
 465       else
 466         {
 467           result = fcntl (fd, F_DUPFD, target);
 468           if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
 469             {
 470               int saved_errno = errno;
 471               close (result);
 472               result = -1;
 473               errno = saved_errno;
 474             }
 475 # if REPLACE_FCHDIR
 476           if (0 <= result)
 477             result = _gl_register_dup (fd, result);
 478 # endif
 479         }
 480     }
 481 #else
 482   result = fcntl (fd, F_DUPFD, target);
 483 #endif
 484   return result;
 485 }
 486 
 487 static int
 488 rpl_fcntl_DUPFD_CLOEXEC (int fd, int target)
     
 489 {
 490   int result;
 491 #if !HAVE_FCNTL
 492   result = dupfd (fd, target, O_CLOEXEC);
 493 #else 
 494 # if defined __NetBSD__ || defined __HAIKU__
 495   
 496 
 497   
 498 
 499 
 500 #  define have_dupfd_cloexec -1
 501 # else
 502   
 503 
 504 
 505 
 506 
 507 
 508 
 509   static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
 510   if (0 <= have_dupfd_cloexec)
 511     {
 512       result = fcntl (fd, F_DUPFD_CLOEXEC, target);
 513       if (0 <= result || errno != EINVAL)
 514         {
 515           have_dupfd_cloexec = 1;
 516 #  if REPLACE_FCHDIR
 517           if (0 <= result)
 518             result = _gl_register_dup (fd, result);
 519 #  endif
 520         }
 521       else
 522         {
 523           result = rpl_fcntl_DUPFD (fd, target);
 524           if (result >= 0)
 525             have_dupfd_cloexec = -1;
 526         }
 527     }
 528   else
 529 # endif
 530     result = rpl_fcntl_DUPFD (fd, target);
 531   if (0 <= result && have_dupfd_cloexec == -1)
 532     {
 533       int flags = fcntl (result, F_GETFD);
 534       if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
 535         {
 536           int saved_errno = errno;
 537           close (result);
 538           errno = saved_errno;
 539           result = -1;
 540         }
 541     }
 542 #endif 
 543   return result;
 544 }
 545 
 546 #undef fcntl
 547 
 548 #ifdef __KLIBC__
 549 
 550 static int
 551 klibc_fcntl (int fd, int action, ...)
     
 552 {
 553   va_list arg_ptr;
 554   int arg;
 555   struct stat sbuf;
 556   int result;
 557 
 558   va_start (arg_ptr, action);
 559   arg = va_arg (arg_ptr, int);
 560   result = fcntl (fd, action, arg);
 561   
 562   if (result == -1 && (errno == EPERM || errno == ENOTSUP)
 563       && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
 564     {
 565       ULONG ulMode;
 566 
 567       switch (action)
 568         {
 569         case F_DUPFD:
 570           
 571           while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
 572             arg++;
 573 
 574           result = dup2 (fd, arg);
 575           break;
 576 
 577         
 578         case F_GETFD:
 579           if (DosQueryFHState (fd, &ulMode))
 580             break;
 581 
 582           result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
 583           break;
 584 
 585         case F_SETFD:
 586           if (arg & ~FD_CLOEXEC)
 587             break;
 588 
 589           if (DosQueryFHState (fd, &ulMode))
 590             break;
 591 
 592           if (arg & FD_CLOEXEC)
 593             ulMode |= OPEN_FLAGS_NOINHERIT;
 594           else
 595             ulMode &= ~OPEN_FLAGS_NOINHERIT;
 596 
 597           
 598           ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
 599                      | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
 600 
 601           if (DosSetFHState (fd, ulMode))
 602             break;
 603 
 604           result = 0;
 605           break;
 606 
 607         case F_GETFL:
 608           result = 0;
 609           break;
 610 
 611         case F_SETFL:
 612           if (arg != 0)
 613             break;
 614 
 615           result = 0;
 616           break;
 617 
 618         default:
 619           errno = EINVAL;
 620           break;
 621         }
 622     }
 623 
 624   va_end (arg_ptr);
 625 
 626   return result;
 627 }
 628 
 629 #endif