If I have a buffer which contains the data of a file, how can I get a file descriptor from it? This is a question derived from how to untar file in memory
3 Answers
I wrote a simple example how to make filedescriptor to a memory area:
#include <unistd.h> #include <stdio.h> #include <string.h> char buff[]="qwer\nasdf\n"; int main(){ int p[2]; pipe(p); if( !fork() ){ for( int buffsize=strlen(buff), len=0; buffsize>len; ) len+=write( p[1], buff+len, buffsize-len ); return 0; } close(p[1]); FILE *f = fdopen( p[0], "r" ); char buff[100]; while( fgets(buff,100,f) ){ printf("from child: '%s'\n", buff ); } puts(""); } 7 Comments
vmsplice() might be useful: it avoids the need for a for-loop to write data to the pipe.fmemopen()? Yes, it's POSIX and not C, but pipe() is also POSIX, isn't it?fileno() will return -1 when called on a FILE* returned from fmemopen().man fmemopen says "There is no file descriptor associated with the file stream returned by this function (i.e., fileno(3) will return an error if called on the returned stream)." It doesn't say why it doesn't work, though. I'm a bit bummed it doesn't.Not possible in plain C. In plain C all file access happens via FILE * handles and these can only be created with fopen() and freopen() and in both cases must refer to a file path. As C tries to be as portable as possible, it limits I/O to the absolute bare minimum that probably all systems can support in some way.
If you have POSIX API available (e.g. Linux, macOS, iOS, FreeBSD, most other UNIX systems), you can use fmemopen():
char dataInMemory[] = "This is some data in memory"; FILE * fileDescriptor = fmemopen(dataInMemory, sizeof(dataInMemory), "r"); This is a true file handle that can be used with all C file API. It should also allow seeking, something not possible if you work with pipes as pipes support no seeking (you can emulate forward seeking but there is no way to ever seek backwards).
Comments
You can't. Unlike C++, the C model of file I/O isn't open to extension.