Revision | 4f506bb95ad4bc55e6174cef98803802a35b050e (tree) |
---|---|
Time | 2019-06-21 19:09:36 |
Author | Denys Vlasenko <dvlasenk@redh...> |
Commiter | Waldemar Brodkorb |
fix opendir, fpathconf and ttyname_r to use fstat64(), not fstat()
There is no opendir64(), thus even programs built for 64-bit off_t
use opendir(). Before this change, internally opendir() uses fstat(),
with the following breakage if some of struct stat fields are too narrow:
$ strace ls -l
execve("/busybox/ls", ["ls", "-l"], 0x7ffcdc43ede8 /* 16 vars */) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
getuid32() = 0
time([1551486393 /* 2019-03-02T00:26:33+0000 */]) = 1551486393 (2019-03-02T00:26:33+0000)
ioctl(0, TIOCGWINSZ, {ws_row=38, ws_col=120, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
brk(NULL) = 0x9768000
brk(0x9769000) = 0x9769000
lstat64(".", 0xffa6e374) = 0
open(".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, 0xffa6e378) = -1 EOVERFLOW (Value too large for defined data type)
See https://bugs.busybox.net/show_bug.cgi?id=11651
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
@@ -16,6 +16,9 @@ | ||
16 | 16 | #include <dirent.h> |
17 | 17 | #include "dirstream.h" |
18 | 18 | |
19 | +#define STAT stat64 | |
20 | +#define FSTAT fstat64 | |
21 | + | |
19 | 22 | static DIR *fd_to_DIR(int fd, __blksize_t size) |
20 | 23 | { |
21 | 24 | DIR *ptr; |
@@ -43,9 +46,9 @@ static DIR *fd_to_DIR(int fd, __blksize_t size) | ||
43 | 46 | DIR *fdopendir(int fd) |
44 | 47 | { |
45 | 48 | int flags; |
46 | - struct stat st; | |
49 | + struct STAT st; | |
47 | 50 | |
48 | - if (fstat(fd, &st)) | |
51 | + if (FSTAT(fd, &st)) | |
49 | 52 | return NULL; |
50 | 53 | if (!S_ISDIR(st.st_mode)) { |
51 | 54 | __set_errno(ENOTDIR); |
@@ -69,12 +72,12 @@ DIR *fdopendir(int fd) | ||
69 | 72 | DIR *opendir(const char *name) |
70 | 73 | { |
71 | 74 | int fd; |
72 | - struct stat statbuf; | |
75 | + struct STAT statbuf; | |
73 | 76 | DIR *ptr; |
74 | 77 | |
75 | 78 | #ifndef O_DIRECTORY |
76 | 79 | /* O_DIRECTORY is linux specific and has been around since like 2.1.x */ |
77 | - if (stat(name, &statbuf)) | |
80 | + if (STAT(name, &statbuf)) | |
78 | 81 | return NULL; |
79 | 82 | if (!S_ISDIR(statbuf.st_mode)) { |
80 | 83 | __set_errno(ENOTDIR); |
@@ -90,7 +93,7 @@ DIR *opendir(const char *name) | ||
90 | 93 | * defined and since Linux has supported it for like ever, i'm not going |
91 | 94 | * to worry about it right now (if ever). */ |
92 | 95 | |
93 | - if (fstat(fd, &statbuf) < 0) { | |
96 | + if (FSTAT(fd, &statbuf) < 0) { | |
94 | 97 | /* this close() never fails |
95 | 98 | *int saved_errno; |
96 | 99 | *saved_errno = errno; */ |
@@ -31,6 +31,9 @@ | ||
31 | 31 | #include <dirent.h> |
32 | 32 | #include <sys/stat.h> |
33 | 33 | |
34 | +#define STAT stat64 | |
35 | +#define FSTAT fstat64 | |
36 | +#define LSTAT lstat64 | |
34 | 37 | |
35 | 38 | #define TTYNAME_BUFLEN 32 |
36 | 39 |
@@ -45,8 +48,8 @@ static const char dirlist[] = | ||
45 | 48 | int ttyname_r(int fd, char *ubuf, size_t ubuflen) |
46 | 49 | { |
47 | 50 | struct dirent *d; |
48 | - struct stat st; | |
49 | - struct stat dst; | |
51 | + struct STAT st; | |
52 | + struct STAT dst; | |
50 | 53 | const char *p; |
51 | 54 | char *s; |
52 | 55 | DIR *fp; |
@@ -54,7 +57,7 @@ int ttyname_r(int fd, char *ubuf, size_t ubuflen) | ||
54 | 57 | size_t len; |
55 | 58 | char buf[TTYNAME_BUFLEN]; |
56 | 59 | |
57 | - if (fstat(fd, &st) < 0) { | |
60 | + if (FSTAT(fd, &st) < 0) { | |
58 | 61 | return errno; |
59 | 62 | } |
60 | 63 |
@@ -86,7 +89,7 @@ int ttyname_r(int fd, char *ubuf, size_t ubuflen) | ||
86 | 89 | |
87 | 90 | strcpy(s, d->d_name); |
88 | 91 | |
89 | - if ((lstat(buf, &dst) == 0) | |
92 | + if ((LSTAT(buf, &dst) == 0) | |
90 | 93 | #if 0 |
91 | 94 | /* Stupid filesystems like cramfs fail to guarantee that |
92 | 95 | * st_ino and st_dev uniquely identify a file, contrary to |
@@ -24,6 +24,8 @@ | ||
24 | 24 | #include <sys/stat.h> |
25 | 25 | #include <sys/statfs.h> |
26 | 26 | |
27 | +#define STAT stat64 | |
28 | +#define FSTAT fstat64 | |
27 | 29 | |
28 | 30 | #ifndef __USE_FILE_OFFSET64 |
29 | 31 | extern int fstatfs (int __fildes, struct statfs *__buf) |
@@ -205,9 +207,9 @@ long int fpathconf(int fd, int name) | ||
205 | 207 | #if defined _POSIX_ASYNC_IO |
206 | 208 | { |
207 | 209 | /* AIO is only allowed on regular files and block devices. */ |
208 | - struct stat st; | |
210 | + struct STAT st; | |
209 | 211 | |
210 | - if (fstat (fd, &st) < 0 || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode))) | |
212 | + if (FSTAT (fd, &st) < 0 || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode))) | |
211 | 213 | return -1; |
212 | 214 | else |
213 | 215 | return 1; |