Change read/write permissions on a file descriptor
Asked Answered
S

2

13

I'm working on a linux C project and I'm having trouble working with file descriptors.

I have an orphan file descriptor (the file was open()'d then unlink()'d but the fd is still good) that has write-only permission. The original backing file had full permissions (created with S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), but alas the file was opened with O_WRONLY. Is it possible to duplicate the file descriptor and change the copy to O_RDWR?

psudo-code:


//open orphan file
int fd = open(fname, O_WRONLY, ...)
unlink(fname)
//fd is still good, but I can't read from it

//...

//I want to be able to read from orphan file
int fd2 = dup(fd)
//----change fd2 to read/write???----

Thanks in advance! -Andrew

Schade answered 9/1, 2011 at 3:29 Comment(12)
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_RDWR)) seems like it would be the thing, except the man page specifically says that won't work. I guess there's some reason the kernel "needs" this to be impossible?Jennee
so why do you open it in wronly mode if you plan to read it?Lorrianelorrie
Or just open it again using the correct flags.Heteronomy
I guess I like to make things difficult for myself. My code doesn't create the orphan file, but reimplementing to wheel is fun, so maybe I'll have toSchade
I would assume if a file has been unlinked and the only references to it are write-only, the kernel would be perfectly justified in deleting it and replacing it with the equivalent of /dev/null, i.e. discarding all further data written and just keeping a dummy file position.Roulette
@aschepler: You need to remove the O_WRONLY flag before adding O_RDWR. O_WRONLY|O_RDWR != O_RDWR.Roulette
@R..: Linux doesn't allow changing fd access mode. The fcntl call may not fail, but any attempt to read that fd will return an error, effectively setting errno to EBADF.Heteronomy
Odd, how is freopen implemented then? Does it just fail? (It's allowed to fail.)Roulette
@R..: under Linux the very same rules apply. It isn't allowed to change access modes, and also doesn't return an error (in this case a NULL stream). Any attempt to read/write will cause EBADF too. If you want a reason for not allowing it, imagine changing stdin to allow writes, and stdout to allow reads - nonsenseHeteronomy
In general, it seems to me that linux allows some nonsense things to happen for the sake of flexibility. If there was such a function (which I'm hoping there is) and you did change access modes of stdin, that wouldn't buy you much. However, if there isn't such a function, it would make it inconvenient in situations like this.Schade
Yes, on Linux you can do this by opening /proc/self/fd/n. See this stackoverflow answer for source code.Hosbein
no need @Hosbein see my answer.Argufy
S
7

No, there is no POSIX function to change the open mode. You will need to open it in read / write mode. Since you are created a temporary file, though, I strongly recommend that you use mkstemp. That function properly opens the file in read/write mode and unlinks it. Most importantly, it avoids a race condition in naming and creating the file, thereby avoiding a vulnerability in the creation of temporary files.

Siddon answered 9/1, 2011 at 3:38 Comment(2)
mkstemp doesn't unlink AFAIK?Lorrianelorrie
what MK said. I can always add O_EXCL to open() and retry on failSchade
A
-2
int fd = open(fname, O_WRONLY, ...)
int fd_ro = open(fname, O_RDONLY, ...)
unlink(fname)
{ write to fd }
close (fd);
read or execute(!) fd_ro
Argufy answered 21/4, 2018 at 15:56 Comment(1)
add some details pleaseOrdain

© 2022 - 2024 — McMap. All rights reserved.