- ensure_dirs_slot (fd);
- if (fd < dirs_allocated
- && (REPLACE_OPEN_DIRECTORY
- || (fstat (fd, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))))
+ assert (0 <= fd);
+ if (REPLACE_OPEN_DIRECTORY
+ || (fstat (fd, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)))
+ {
+ if (!ensure_dirs_slot (fd)
+ || (dirs[fd].name = get_name (filename)) == NULL)
+ {
+ int saved_errno = errno;
+ close (fd);
+ errno = saved_errno;
+ return -1;
+ }
+ }
+ return fd;
+}
+
+/* Mark NEWFD as a duplicate of OLDFD; useful from dup, dup2, dup3,
+ and fcntl. Both arguments must be valid and distinct file
+ descriptors. Close NEWFD and return -1 if OLDFD is tracking a
+ directory, but there is insufficient memory to track the same
+ directory in NEWFD; otherwise return NEWFD.
+
+ FIXME: Need to implement rpl_fcntl in gnulib, and have it call
+ this. */
+int
+_gl_register_dup (int oldfd, int newfd)
+{
+ assert (0 <= oldfd && 0 <= newfd && oldfd != newfd);
+ if (oldfd < dirs_allocated && dirs[oldfd].name)
+ {
+ /* Duplicated a directory; must ensure newfd is allocated. */
+ if (!ensure_dirs_slot (newfd)
+ || (dirs[newfd].name = strdup (dirs[oldfd].name)) == NULL)
+ {
+ int saved_errno = errno;
+ close (newfd);
+ errno = saved_errno;
+ newfd = -1;
+ }
+ }
+ else if (newfd < dirs_allocated)