...
Since the behavior of O_NONBLOCK on subsequent calls to read() or write() is unspecified, it is advisable to disable the flag once we are sure the file in question is not a special device.
| Wiki Markup |
|---|
When available (Linux 2.1.26+, FreeBSD, Solaris 10, POSIX.1-2008), the {{O_NOFOLLOW}} should also be used, see \[[POS01-A. Check for the existence of links]\] |
| Code Block | ||
|---|---|---|
| ||
#ifdef O_NOFOLLOW
#define OPEN_FLAGS O_NOFOLLOW | O_NONBLOCK
#else
#define OPEN_FLAGS O_NONBLOCK
#endif
/* ... */
struct stat orig_st;
struct stat open_st;
int fildes;
int flags;
if (!fgets(filename, sizeof(filename), stdin)) {
/* handle error */
}
if ((stat(file_name, &orig_st) != 0) || (!S_ISREG(orig_st.st_mode))) {
/* handle error */
}
/* A TOCTOU exists here, see note */
if ((fildes = open(filename, OPEN_FLAGS, O_WRONLY)) == -1) {
/* handle error */
}
if (fstat(fildes, &open_st) != 0) {
/* handle error */
}
if ((orig_st.st_mode != open_st.st_mode) ||
(orig_st.st_ino != open_st.st_ino) ||
(orig_st.st_dev != open_st.st_dev)) {
/* file was tampered with */
}
/* Optional: drop the O_NONBLOCK now that we are sure this is a good file */
if ((flags = fcntl(fildes, F_GETFL)) == -1) {
/* handle error */
}
if ((fcntl(fildes, F_SETFL, flags & ~O_NONBLOCK) != 0) {
/* handle error */
}
/* operate on file */
|
...