See title.
How do I achieve the opposite of this question: How do I get the file HANDLE from the fopen FILE structure?
I create the handle with
HANDLE h = CreateFile(name,
GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
and then try to write some data to it using fputs.
The call to fputs fails on the line
_VALIDATE_STREAM_ANSI_RETURN(stream, EINVAL, EOF);
where stream is the handle I obtained from CreateFile.
The reason why I'm doing that is that I use an external library that uses FILE* handles and I'm not opening a plain file (as until now) but trying to write to a pipe instead. And changing the external library is not an option.
Don't know if this is the best way but see _open_osfhandle():
http://msdn.microsoft.com/en-us/library/bdts1c9x(v=vs.71).aspx
int fd = _open_osfhandle(h, ...);
It returns a file descriptor which you'll have to open using fdopen to get a FILE*.
FILE* fp = _fdopen(fd, ...);
Related
How to block file when you reading it (by fopen or open in linux), to prevent any modifications during reading?
What i have: 1 file with data; I want to read data from it in my function, so i use fopen():
FILE *file = fopen(fileName, "r");
Now i need something to block my file - any (or only current user's as variant) another process mustn't have any access (or only modify it as variant) to it until my function will allow them to do it
I suppose, i can do that using set chmod flags for them and setting them back after work;
Or using open() function with special flags arguments, but it's not desirable because i would like to work with fgets() in function;
Is there any examples of how to do it?
Yes, you can use flock to do this. However, since you want to open the file with fopen instead of open, you'll need to first get the file descriptor using fileno. For example:
FILE* f = fopen(...);
int fd = fileno(f);
// flock should return zero on success
flock(fd, LOCK_EX);
That would place an exclusive lock - if you want a shared lock, change LOCK_EX to LOCK_SH.
I need to read a file opened like this:
int outfile = open(*fileName, "w");
using the file descriptor, I'm doing that like this:
char txt[50];
int bytes;
bytes = read(outfile,txt, 50);
But I'm getting segmentation fault and the application abort, any ideas?
Note the second argument to open. It's "w" this seems like it should indicate that you're opening the file for writing. However, my man pages for open indicates that the second argument should be one of: O_RDONLY, O_WRONLY, or O_RDWR. (fopen uses strings like "w", "w+", "r", ... but that's fopen not open). You may be getting lucky that the value of "w" as an int sets you up for writing but you really want to check your return values and probably want to use
open(*filename, O_RDWR);
to set up the mode for reading and writing.
I have to use a certain cross-platform library which passes FILE* objects around.
I get a file descriptor from another source (inherited), I want to keep same fd across fork'd processes.
I currently use fdopen to convert a file descriptor to a FILE* object.
My problem is that fclose used to clean up FILE* objects closes connected file descriptor.
I would very much like to keep this file descriptor after it has been used.
is there a way rescue file descriptor from FILE*?
Is there a way to detach it?
Or a way to substitute a file descriptor in FILE* with a dummy?
P.S. this needs to be cross-platform, well across POSIX anyway.
Supposing that fd is your file descriptor and f your FILE* got from it. Maybe something like the following will do the trick:
fd2 = dup(fd);
fclose(f);
dup2(fd2, fd);
close(fd2);
My problem is that fclose used to clean up FILE* objects closes
connected file descriptor.
You could use dup(2) to get a copy of the descriptor. Then the close(2) that fclose(3) does won't do anything.
I need to maintain exact same fd number
Then call dup2 again after fclose: dup2(savedfd, rescuedfd)
When you get a file descriptor from another source, Try to get its filename from that file descriptor. (Some says its possible using platform specific method. -google it.)
Once you get filename then fopen it again and get FILE* and do your work and clean up it using fclose.
Your original fd will not be disturbed.
Here's a non-portable idea (vote if you think this is good/best):
GNU libc provides fopencookie and BSD provides equivalent funopen.
These return real FILE* handle, but implementation is your own:
It is then relatively trivial to map read/write/seek/close functions to underlying system calls:
read/readfn(cookie, buf, size){ return read((int)cookie, buf, size); }
write/writefn(cookie, buf, size) { return write((int)cookie, buf, size); }
seek/seekfn(cookie, offs, arg) { return seek((int)cookie, offs, arg); } // may require arg mapping to whence
close/closefn(cookie) {} // that's the whole point!
In Unix, if you have a file descriptor (e.g. from a socket, pipe, or inherited from your parent process), you can open a buffered I/O FILE* stream on it with fdopen(3).
Is there an equivalent on Windows for HANDLEs? If you have a HANDLE that was inherited from your parent process (different from stdin, stdout, or stderr) or a pipe from CreatePipe, is it possible to get a buffered FILE* stream from it? MSDN does document _fdopen, but that works with integer file descriptors returned by _open, not generic HANDLEs.
Unfortunately, HANDLEs are completely different beasts from FILE*s and file descriptors. The CRT ultimately handles files in terms of HANDLEs and associates those HANDLEs to a file descriptor. Those file descriptors in turn backs the structure pointer by FILE*.
Fortunately, there is a section on this MSDN page that describes functions that "provide a way to change the representation of the file between a FILE structure, a file descriptor, and a Win32 file handle":
_fdopen, _wfdopen: Associates a stream with a file that was
previously opened for low-level I/O and returns a pointer to the open
stream.
_fileno: Gets the file descriptor associated with a stream.
_get_osfhandle: Return operating-system file handle associated
with existing C run-time file descriptor
_open_osfhandle: Associates C run-time file descriptor with an
existing operating-system file handle.
Looks like what you need is _open_osfhandle followed by _fdopen to obtain a FILE* from a HANDLE.
Here's an example involving HANDLEs obtained from CreateFile(). When I tested it, it shows the first 255 characters of the file "test.txt" and appends " --- Hello World! --- " at the end of the file:
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <cstdio>
int main()
{
HANDLE h = CreateFile("test.txt", GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(h != INVALID_HANDLE_VALUE)
{
int fd = _open_osfhandle((intptr_t)h, _O_APPEND | _O_RDONLY);
if(fd != -1)
{
FILE* f = _fdopen(fd, "a+");
if(f != 0)
{
char rbuffer[256];
memset(rbuffer, 0, 256);
fread(rbuffer, 1, 255, f);
printf("read: %s\n", rbuffer);
fseek(f, 0, SEEK_CUR); // Switch from read to write
const char* wbuffer = " --- Hello World! --- \n";
fwrite(wbuffer, 1, strlen(wbuffer), f);
fclose(f); // Also calls _close()
}
else
{
_close(fd); // Also calls CloseHandle()
}
}
else
{
CloseHandle(h);
}
}
}
This should work for pipes as well.
Here is a more elegant way of doing this instead of CreateFile: specify "N" in fopen(). It's a Microsoft-specific extension to fopen, but since this code is platform-specific anyway, it's ok. When called with "N", fopen adds _O_NOINHERIT flag when calling _open internally.
Based on this:
Windows C Run-Time _close(fd) not closing file
I'm opening a stream with funopen
FILE *fin = funopen(cookie, readfn, NULL, NULL, closefn);
if (fin == NULL)
{
handle_error();
return -1;
}
int fdin = fileno(fin);
The call to funopen succeeds but fileno(fin) returns -1.
How can I get the file descriptor? Thanks.
A FILE opened with funopen (which is not part of any standard, by the way; AFAIK it's a BSD extension) does not have an underlying file descriptor. It has the cookie instead. I don't know what you wanted the file descriptor for, but you're probably out of luck.
There's no file connected to funopen, and thus no fd. Try tmpfile instead if you need that.