1 | /* Create /proc/self/fd-related names for subfiles of open directories.
|
---|
2 |
|
---|
3 | Copyright (C) 2006 Free Software Foundation, Inc.
|
---|
4 |
|
---|
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 2, or (at your option)
|
---|
8 | any later version.
|
---|
9 |
|
---|
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.
|
---|
14 |
|
---|
15 | You should have received a copy of the GNU General Public License
|
---|
16 | along with this program; if not, write to the Free Software Foundation,
|
---|
17 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
---|
18 |
|
---|
19 | /* Written by Paul Eggert. */
|
---|
20 |
|
---|
21 | #include <config.h>
|
---|
22 |
|
---|
23 | #include "openat-priv.h"
|
---|
24 |
|
---|
25 | #include <sys/types.h>
|
---|
26 | #include <sys/stat.h>
|
---|
27 | #include <fcntl.h>
|
---|
28 |
|
---|
29 | #include <stdio.h>
|
---|
30 | #include <string.h>
|
---|
31 |
|
---|
32 | #include "dirname.h"
|
---|
33 | #include "intprops.h"
|
---|
34 | #include "same-inode.h"
|
---|
35 | #include "xalloc.h"
|
---|
36 |
|
---|
37 | #define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/%s"
|
---|
38 |
|
---|
39 | #define PROC_SELF_FD_NAME_SIZE_BOUND(len) \
|
---|
40 | (sizeof PROC_SELF_FD_FORMAT - sizeof "%d%s" \
|
---|
41 | + INT_STRLEN_BOUND (int) + (len) + 1)
|
---|
42 |
|
---|
43 |
|
---|
44 | /* Set BUF to the expansion of PROC_SELF_FD_FORMAT, using FD and FILE
|
---|
45 | respectively for %d and %s. If successful, return BUF if the
|
---|
46 | result fits in BUF, dynamically allocated memory otherwise. But
|
---|
47 | return NULL if /proc is not reliable. */
|
---|
48 | char *
|
---|
49 | openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file)
|
---|
50 | {
|
---|
51 | static int proc_status = 0;
|
---|
52 |
|
---|
53 | if (! proc_status)
|
---|
54 | {
|
---|
55 | /* Set PROC_STATUS to a positive value if /proc/self/fd is
|
---|
56 | reliable, and a negative value otherwise. Solaris 10
|
---|
57 | /proc/self/fd mishandles "..", and any file name might expand
|
---|
58 | to ".." after symbolic link expansion, so avoid /proc/self/fd
|
---|
59 | if it mishandles "..". Solaris 10 has openat, but this
|
---|
60 | problem is exhibited on code that built on Solaris 8 and
|
---|
61 | running on Solaris 10. */
|
---|
62 |
|
---|
63 | int proc_self_fd = open ("/proc/self/fd", O_RDONLY);
|
---|
64 | if (proc_self_fd < 0)
|
---|
65 | proc_status = -1;
|
---|
66 | else
|
---|
67 | {
|
---|
68 | struct stat proc_self_fd_dotdot_st;
|
---|
69 | struct stat proc_self_st;
|
---|
70 | char dotdot_buf[PROC_SELF_FD_NAME_SIZE_BOUND (sizeof ".." - 1)];
|
---|
71 | sprintf (dotdot_buf, PROC_SELF_FD_FORMAT, proc_self_fd, "..");
|
---|
72 | proc_status =
|
---|
73 | ((stat (dotdot_buf, &proc_self_fd_dotdot_st) == 0
|
---|
74 | && stat ("/proc/self", &proc_self_st) == 0
|
---|
75 | && SAME_INODE (proc_self_fd_dotdot_st, proc_self_st))
|
---|
76 | ? 1 : -1);
|
---|
77 | close (proc_self_fd);
|
---|
78 | }
|
---|
79 | }
|
---|
80 |
|
---|
81 | if (proc_status < 0)
|
---|
82 | return NULL;
|
---|
83 | else
|
---|
84 | {
|
---|
85 | size_t bufsize = PROC_SELF_FD_NAME_SIZE_BOUND (strlen (file));
|
---|
86 | char *result = (bufsize < OPENAT_BUFFER_SIZE ? buf : xmalloc (bufsize));
|
---|
87 | sprintf (result, PROC_SELF_FD_FORMAT, fd, file);
|
---|
88 | return result;
|
---|
89 | }
|
---|
90 | }
|
---|