Output alists with dotted pair notation in .dir-locals.el
[emacs.git] / lib / fcntl.c
blob8e976173c0b828f6b63db2ef82777dbe64a728e9
1 /* Provide file descriptor control.
3 Copyright (C) 2009-2018 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Written by Eric Blake <ebb9@byu.net>. */
20 #include <config.h>
22 /* Specification. */
23 #include <fcntl.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdarg.h>
28 #include <unistd.h>
30 #if !HAVE_FCNTL
31 # define rpl_fcntl fcntl
32 #endif
33 #undef fcntl
35 #if defined _WIN32 && ! defined __CYGWIN__
36 /* Get declarations of the native Windows API functions. */
37 # define WIN32_LEAN_AND_MEAN
38 # include <windows.h>
40 /* Get _get_osfhandle. */
41 # if GNULIB_MSVC_NOTHROW
42 # include "msvc-nothrow.h"
43 # else
44 # include <io.h>
45 # endif
47 /* Upper bound on getdtablesize(). See lib/getdtablesize.c. */
48 # define OPEN_MAX_MAX 0x10000
50 /* Duplicate OLDFD into the first available slot of at least NEWFD,
51 which must be positive, with FLAGS determining whether the duplicate
52 will be inheritable. */
53 static int
54 dupfd (int oldfd, int newfd, int flags)
56 /* Mingw has no way to create an arbitrary fd. Iterate until all
57 file descriptors less than newfd are filled up. */
58 HANDLE curr_process = GetCurrentProcess ();
59 HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd);
60 unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
61 unsigned int fds_to_close_bound = 0;
62 int result;
63 BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
64 int mode;
66 if (newfd < 0 || getdtablesize () <= newfd)
68 errno = EINVAL;
69 return -1;
71 if (old_handle == INVALID_HANDLE_VALUE
72 || (mode = setmode (oldfd, O_BINARY)) == -1)
74 /* oldfd is not open, or is an unassigned standard file
75 descriptor. */
76 errno = EBADF;
77 return -1;
79 setmode (oldfd, mode);
80 flags |= mode;
82 for (;;)
84 HANDLE new_handle;
85 int duplicated_fd;
86 unsigned int index;
88 if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
89 old_handle, /* SourceHandle */
90 curr_process, /* TargetProcessHandle */
91 (PHANDLE) &new_handle, /* TargetHandle */
92 (DWORD) 0, /* DesiredAccess */
93 inherit, /* InheritHandle */
94 DUPLICATE_SAME_ACCESS)) /* Options */
96 switch (GetLastError ())
98 case ERROR_TOO_MANY_OPEN_FILES:
99 errno = EMFILE;
100 break;
101 case ERROR_INVALID_HANDLE:
102 case ERROR_INVALID_TARGET_HANDLE:
103 case ERROR_DIRECT_ACCESS_HANDLE:
104 errno = EBADF;
105 break;
106 case ERROR_INVALID_PARAMETER:
107 case ERROR_INVALID_FUNCTION:
108 case ERROR_INVALID_ACCESS:
109 errno = EINVAL;
110 break;
111 default:
112 errno = EACCES;
113 break;
115 result = -1;
116 break;
118 duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags);
119 if (duplicated_fd < 0)
121 CloseHandle (new_handle);
122 result = -1;
123 break;
125 if (newfd <= duplicated_fd)
127 result = duplicated_fd;
128 break;
131 /* Set the bit duplicated_fd in fds_to_close[]. */
132 index = (unsigned int) duplicated_fd / CHAR_BIT;
133 if (fds_to_close_bound <= index)
135 if (sizeof fds_to_close <= index)
136 /* Need to increase OPEN_MAX_MAX. */
137 abort ();
138 memset (fds_to_close + fds_to_close_bound, '\0',
139 index + 1 - fds_to_close_bound);
140 fds_to_close_bound = index + 1;
142 fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT);
145 /* Close the previous fds that turned out to be too small. */
147 int saved_errno = errno;
148 unsigned int duplicated_fd;
150 for (duplicated_fd = 0;
151 duplicated_fd < fds_to_close_bound * CHAR_BIT;
152 duplicated_fd++)
153 if ((fds_to_close[duplicated_fd / CHAR_BIT]
154 >> (duplicated_fd % CHAR_BIT))
155 & 1)
156 close (duplicated_fd);
158 errno = saved_errno;
161 # if REPLACE_FCHDIR
162 if (0 <= result)
163 result = _gl_register_dup (oldfd, result);
164 # endif
165 return result;
167 #endif /* W32 */
169 #ifdef __KLIBC__
171 # define INCL_DOS
172 # include <os2.h>
174 static int
175 klibc_fcntl (int fd, int action, /* arg */...)
177 va_list arg_ptr;
178 int arg;
179 struct stat sbuf;
180 int result = -1;
182 va_start (arg_ptr, action);
183 arg = va_arg (arg_ptr, int);
184 result = fcntl (fd, action, arg);
185 /* EPERM for F_DUPFD, ENOTSUP for others */
186 if (result == -1 && (errno == EPERM || errno == ENOTSUP)
187 && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
189 ULONG ulMode;
191 switch (action)
193 case F_DUPFD:
194 /* Find available fd */
195 while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
196 arg++;
198 result = dup2 (fd, arg);
199 break;
201 /* Using underlying APIs is right ? */
202 case F_GETFD:
203 if (DosQueryFHState (fd, &ulMode))
204 break;
206 result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
207 break;
209 case F_SETFD:
210 if (arg & ~FD_CLOEXEC)
211 break;
213 if (DosQueryFHState (fd, &ulMode))
214 break;
216 if (arg & FD_CLOEXEC)
217 ulMode |= OPEN_FLAGS_NOINHERIT;
218 else
219 ulMode &= ~OPEN_FLAGS_NOINHERIT;
221 /* Filter supported flags. */
222 ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
223 | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
225 if (DosSetFHState (fd, ulMode))
226 break;
228 result = 0;
229 break;
231 case F_GETFL:
232 result = 0;
233 break;
235 case F_SETFL:
236 if (arg != 0)
237 break;
239 result = 0;
240 break;
242 default :
243 errno = EINVAL;
244 break;
248 va_end (arg_ptr);
250 return result;
253 # define fcntl klibc_fcntl
254 #endif
256 /* Perform the specified ACTION on the file descriptor FD, possibly
257 using the argument ARG further described below. This replacement
258 handles the following actions, and forwards all others on to the
259 native fcntl. An unrecognized ACTION returns -1 with errno set to
260 EINVAL.
262 F_DUPFD - duplicate FD, with int ARG being the minimum target fd.
263 If successful, return the duplicate, which will be inheritable;
264 otherwise return -1 and set errno.
266 F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum
267 target fd. If successful, return the duplicate, which will not be
268 inheritable; otherwise return -1 and set errno.
270 F_GETFD - ARG need not be present. If successful, return a
271 non-negative value containing the descriptor flags of FD (only
272 FD_CLOEXEC is portable, but other flags may be present); otherwise
273 return -1 and set errno. */
276 rpl_fcntl (int fd, int action, /* arg */...)
278 va_list arg;
279 int result = -1;
280 va_start (arg, action);
281 switch (action)
284 #if !HAVE_FCNTL
285 case F_DUPFD:
287 int target = va_arg (arg, int);
288 result = dupfd (fd, target, 0);
289 break;
291 #elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
292 case F_DUPFD:
294 int target = va_arg (arg, int);
295 /* Detect invalid target; needed for cygwin 1.5.x. */
296 if (target < 0 || getdtablesize () <= target)
297 errno = EINVAL;
298 else
300 /* Haiku alpha 2 loses fd flags on original. */
301 int flags = fcntl (fd, F_GETFD);
302 if (flags < 0)
304 result = -1;
305 break;
307 result = fcntl (fd, action, target);
308 if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
310 int saved_errno = errno;
311 close (result);
312 result = -1;
313 errno = saved_errno;
315 # if REPLACE_FCHDIR
316 if (0 <= result)
317 result = _gl_register_dup (fd, result);
318 # endif
320 break;
321 } /* F_DUPFD */
322 #endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */
324 case F_DUPFD_CLOEXEC:
326 int target = va_arg (arg, int);
328 #if !HAVE_FCNTL
329 result = dupfd (fd, target, O_CLOEXEC);
330 break;
331 #else /* HAVE_FCNTL */
332 # if defined __HAIKU__
333 /* On Haiku, the system fcntl (fd, F_DUPFD_CLOEXEC, target) sets
334 the FD_CLOEXEC flag on fd, not on target. Therefore avoid the
335 system fcntl in this case. */
336 # define have_dupfd_cloexec -1
337 # else
338 /* Try the system call first, if the headers claim it exists
339 (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
340 may be running with a glibc that has the macro but with an
341 older kernel that does not support it. Cache the
342 information on whether the system call really works, but
343 avoid caching failure if the corresponding F_DUPFD fails
344 for any reason. 0 = unknown, 1 = yes, -1 = no. */
345 static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
346 if (0 <= have_dupfd_cloexec)
348 result = fcntl (fd, action, target);
349 if (0 <= result || errno != EINVAL)
351 have_dupfd_cloexec = 1;
352 # if REPLACE_FCHDIR
353 if (0 <= result)
354 result = _gl_register_dup (fd, result);
355 # endif
357 else
359 result = rpl_fcntl (fd, F_DUPFD, target);
360 if (result < 0)
361 break;
362 have_dupfd_cloexec = -1;
365 else
366 # endif
367 result = rpl_fcntl (fd, F_DUPFD, target);
368 if (0 <= result && have_dupfd_cloexec == -1)
370 int flags = fcntl (result, F_GETFD);
371 if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
373 int saved_errno = errno;
374 close (result);
375 errno = saved_errno;
376 result = -1;
379 break;
380 #endif /* HAVE_FCNTL */
381 } /* F_DUPFD_CLOEXEC */
383 #if !HAVE_FCNTL
384 case F_GETFD:
386 # if defined _WIN32 && ! defined __CYGWIN__
387 HANDLE handle = (HANDLE) _get_osfhandle (fd);
388 DWORD flags;
389 if (handle == INVALID_HANDLE_VALUE
390 || GetHandleInformation (handle, &flags) == 0)
391 errno = EBADF;
392 else
393 result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
394 # else /* !W32 */
395 /* Use dup2 to reject invalid file descriptors. No way to
396 access this information, so punt. */
397 if (0 <= dup2 (fd, fd))
398 result = 0;
399 # endif /* !W32 */
400 break;
401 } /* F_GETFD */
402 #endif /* !HAVE_FCNTL */
404 /* Implementing F_SETFD on mingw is not trivial - there is no
405 API for changing the O_NOINHERIT bit on an fd, and merely
406 changing the HANDLE_FLAG_INHERIT bit on the underlying handle
407 can lead to odd state. It may be possible by duplicating the
408 handle, using _open_osfhandle with the right flags, then
409 using dup2 to move the duplicate onto the original, but that
410 is not supported for now. */
412 default:
414 #if HAVE_FCNTL
415 switch (action)
417 #ifdef F_BARRIERFSYNC /* macOS */
418 case F_BARRIERFSYNC:
419 #endif
420 #ifdef F_CHKCLEAN /* macOS */
421 case F_CHKCLEAN:
422 #endif
423 #ifdef F_CLOSEM /* NetBSD, HP-UX */
424 case F_CLOSEM:
425 #endif
426 #ifdef F_FLUSH_DATA /* macOS */
427 case F_FLUSH_DATA:
428 #endif
429 #ifdef F_FREEZE_FS /* macOS */
430 case F_FREEZE_FS:
431 #endif
432 #ifdef F_FULLFSYNC /* macOS */
433 case F_FULLFSYNC:
434 #endif
435 #ifdef F_GETCONFINED /* macOS */
436 case F_GETCONFINED:
437 #endif
438 #ifdef F_GETDEFAULTPROTLEVEL /* macOS */
439 case F_GETDEFAULTPROTLEVEL:
440 #endif
441 #ifdef F_GETFD /* POSIX */
442 case F_GETFD:
443 #endif
444 #ifdef F_GETFL /* POSIX */
445 case F_GETFL:
446 #endif
447 #ifdef F_GETLEASE /* Linux */
448 case F_GETLEASE:
449 #endif
450 #ifdef F_GETNOSIGPIPE /* macOS */
451 case F_GETNOSIGPIPE:
452 #endif
453 #ifdef F_GETOWN /* POSIX */
454 case F_GETOWN:
455 #endif
456 #ifdef F_GETPIPE_SZ /* Linux */
457 case F_GETPIPE_SZ:
458 #endif
459 #ifdef F_GETPROTECTIONCLASS /* macOS */
460 case F_GETPROTECTIONCLASS:
461 #endif
462 #ifdef F_GETPROTECTIONLEVEL /* macOS */
463 case F_GETPROTECTIONLEVEL:
464 #endif
465 #ifdef F_GET_SEALS /* Linux */
466 case F_GET_SEALS:
467 #endif
468 #ifdef F_GETSIG /* Linux */
469 case F_GETSIG:
470 #endif
471 #ifdef F_MAXFD /* NetBSD */
472 case F_MAXFD:
473 #endif
474 #ifdef F_RECYCLE /* macOS */
475 case F_RECYCLE:
476 #endif
477 #ifdef F_SETFIFOENH /* HP-UX */
478 case F_SETFIFOENH:
479 #endif
480 #ifdef F_THAW_FS /* macOS */
481 case F_THAW_FS:
482 #endif
483 /* These actions take no argument. */
484 result = fcntl (fd, action);
485 break;
487 #ifdef F_ADD_SEALS /* Linux */
488 case F_ADD_SEALS:
489 #endif
490 #ifdef F_BADFD /* Solaris */
491 case F_BADFD:
492 #endif
493 #ifdef F_CHECK_OPENEVT /* macOS */
494 case F_CHECK_OPENEVT:
495 #endif
496 #ifdef F_DUP2FD /* FreeBSD, AIX, Solaris */
497 case F_DUP2FD:
498 #endif
499 #ifdef F_DUP2FD_CLOEXEC /* FreeBSD, Solaris */
500 case F_DUP2FD_CLOEXEC:
501 #endif
502 #ifdef F_DUP2FD_CLOFORK /* Solaris */
503 case F_DUP2FD_CLOFORK:
504 #endif
505 #ifdef F_DUPFD /* POSIX */
506 case F_DUPFD:
507 #endif
508 #ifdef F_DUPFD_CLOEXEC /* POSIX */
509 case F_DUPFD_CLOEXEC:
510 #endif
511 #ifdef F_DUPFD_CLOFORK /* Solaris */
512 case F_DUPFD_CLOFORK:
513 #endif
514 #ifdef F_GETXFL /* Solaris */
515 case F_GETXFL:
516 #endif
517 #ifdef F_GLOBAL_NOCACHE /* macOS */
518 case F_GLOBAL_NOCACHE:
519 #endif
520 #ifdef F_MAKECOMPRESSED /* macOS */
521 case F_MAKECOMPRESSED:
522 #endif
523 #ifdef F_MOVEDATAEXTENTS /* macOS */
524 case F_MOVEDATAEXTENTS:
525 #endif
526 #ifdef F_NOCACHE /* macOS */
527 case F_NOCACHE:
528 #endif
529 #ifdef F_NODIRECT /* macOS */
530 case F_NODIRECT:
531 #endif
532 #ifdef F_NOTIFY /* Linux */
533 case F_NOTIFY:
534 #endif
535 #ifdef F_OPLKACK /* IRIX */
536 case F_OPLKACK:
537 #endif
538 #ifdef F_OPLKREG /* IRIX */
539 case F_OPLKREG:
540 #endif
541 #ifdef F_RDAHEAD /* macOS */
542 case F_RDAHEAD:
543 #endif
544 #ifdef F_SETBACKINGSTORE /* macOS */
545 case F_SETBACKINGSTORE:
546 #endif
547 #ifdef F_SETCONFINED /* macOS */
548 case F_SETCONFINED:
549 #endif
550 #ifdef F_SETFD /* POSIX */
551 case F_SETFD:
552 #endif
553 #ifdef F_SETFL /* POSIX */
554 case F_SETFL:
555 #endif
556 #ifdef F_SETLEASE /* Linux */
557 case F_SETLEASE:
558 #endif
559 #ifdef F_SETNOSIGPIPE /* macOS */
560 case F_SETNOSIGPIPE:
561 #endif
562 #ifdef F_SETOWN /* POSIX */
563 case F_SETOWN:
564 #endif
565 #ifdef F_SETPIPE_SZ /* Linux */
566 case F_SETPIPE_SZ:
567 #endif
568 #ifdef F_SETPROTECTIONCLASS /* macOS */
569 case F_SETPROTECTIONCLASS:
570 #endif
571 #ifdef F_SETSIG /* Linux */
572 case F_SETSIG:
573 #endif
574 #ifdef F_SINGLE_WRITER /* macOS */
575 case F_SINGLE_WRITER:
576 #endif
577 /* These actions take an 'int' argument. */
579 int x = va_arg (arg, int);
580 result = fcntl (fd, action, x);
582 break;
584 default:
585 /* Other actions take a pointer argument. */
587 void *p = va_arg (arg, void *);
588 result = fcntl (fd, action, p);
590 break;
592 #else
593 errno = EINVAL;
594 #endif
595 break;
598 va_end (arg);
599 return result;