Get FILE stream from File Handle [duplicate] - winapi

This question already has an answer here:
How do I retrieve the FILE* of a CreateFile result?
(1 answer)
Closed 1 year ago.
I would like to use file stream functions (e.g., "ftell") on an existing file I opened using CreateFile (which returns a HANDLE). I searched SO and elsewhere with no joy. I want to do something like this:
HANDLE h;
FILE *f;
int pos;
h = CreateFile( "MYFILE.TXT", ... )
f = *convert*( h, &f ); // the function I'm looking for
pos = ftell( f );
Is there a way to get a FILE stream from a file handle?

Use _open_osfhandle() to create a C-style file descriptor from a Win32 HANDLE, and then use _fdopen() to create a FILE* from the file descriptor.

Related

Boost::interprocess file_handle_t and read

How can I read the content of boost::interprocess::file_handle_t?
We are currently prototyping with code found at scoped_lock doesn't work on file?. This demonstrates how to write but we would also like to read from the file. How can this be accomplished? Done the normal google search and looked at boost docs and header files without any luck. Appreciate any input.
#include "boost/format.hpp"
#include "boost/interprocess/detail/os_file_functions.hpp"
namespace ip = boost::interprocess;
namespace ipc = boost::interprocess::detail;
void fileLocking_withHandle()
{
static const string filename = "fileLocking_withHandle.txt";
// Get file handle
boost::interprocess::file_handle_t pFile = ipc::create_or_open_file(filename.c_str(), ip::read_write);
if ((pFile == 0 || pFile == ipc::invalid_file()))
{
throw runtime_error(boost::str(boost::format("File Writer fail to open output file: %1%") % filename).c_str());
}
// Lock file
ipc::acquire_file_lock(pFile);
// Move writing pointer to the end of the file
ipc::set_file_pointer(pFile, 0, ip::file_end);
// Write in file
ipc::write_file(pFile, (const void*)("bla"), 3);
// Unlock file
ipc::release_file_lock(pFile);
// Close file
ipc::close_file(pFile);
}
We are developing on Windows and Linux.
To solve the issue we used platform specific method.
So for Windows platform we used ReadFile(..) [#include "Windows"] and for Linux we used read(..) [#include

Acessing CONIN$ without a tty

I am trying to get access to a file descriptor which receives input from the console. I am currently using
HANDLE fd = CreateFile(
"CONIN$",
GENERIC_READ | GENERIC_WRITE,
TRUE,
0,
OPEN_EXISTING,
0,
0);
SetConsoleMode(fd, ENABLE_WINDOW_INPUT);
And returning the fd to a program that reads (based on libuv) the input from the console.
This works fine when the process is executed in the console, but reading from the fd crashes when I pipe input into the program
echo hello | inputProgram
I have a suspicion that there is no console associated with the input process, but I'm not certain. How do I properly read the input into the cmd window when executing in this way?
So I a am binding to this C++ program in Node.js. I call
var ReadStream = require("tty").ReadStream();
var TTY = process.binding("tty_wrap").TTY;
module.exports = function () {
var opentty = require("./bin/opentty.node") // program returns the fd int
var fd = opentty();
var t = new _TTY(fd, true);
return new ReadStream(t);
}
opentty returns 3 in redirected input mode for the file handle. The code that deals with this file handle can be found here
https://github.com/joyent/node/blob/master/src/tty_wrap.cc#L185
which essentially calls into uv_tty_init found here
https://github.com/joyent/node/blob/master/deps/uv/src/win/tty.c#L99
The stream errors with Error: read EBADF, syscall: read
Looking through the Node repository it seems clear that new _TTY(fd, true) is expecting a C file descriptor, but you're passing it a Win32 handle.
The _open_osfhandle function creates a file descriptor from a handle.
So, you should try
var t = new _TTY(_open_osfhandle(fd), true);
(as discussed in the comments, this will only work if you're sharing the C runtime with libuv.)
Ideally you would use libuv's open function, but unfortunately there's a bug in fs__open:
case _O_RDWR:
access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
This is where it decides which access permissions to request. FILE_GENERIC_WRITE and FILE_GENERIC_READ are, as the names suggest, specific to files, and can't be used to open CONIN$. It should be
case _O_RDWR:
access = GENERIC_READ | GENERIC_WRITE;
which will work for both files and other types of objects such as the console input and output. (I've reproduced this in a simple C program; on my system, using the FILE_* permissions definitely prevents you from opening CONIN$.)

Deleting currently loaded files using Qt on Windows

I am trying to delete all the temporary files created by my application during uninstall. I use the following code:
bool DeleteFileNow( QString filenameStr )
{
wchar_t* filename;
filenameStr.toWCharArray(filename);
QFileInfo info(filenameStr);
// don't do anything if the file doesn't exist!
if (!info.exists())
return false;
// determine the path in which to store the temp filename
wchar_t* path;
info.absolutePath().toWCharArray(path);
TRACE( "Generating temporary name" );
// generate a guaranteed to be unique temporary filename to house the pending delete
wchar_t tempname[MAX_PATH];
if (!GetTempFileNameW(path, L".xX", 0, tempname))
return false;
TRACE( "Moving real file name to dummy" );
// move the real file to the dummy filename
if (!MoveFileExW(filename, tempname, MOVEFILE_REPLACE_EXISTING))
{
// clean up the temp file
DeleteFileW(tempname);
return false;
}
TRACE( "Queueing the OS" );
// queue the deletion (the OS will delete it when all handles (ours or other processes) close)
return DeleteFileW(tempname) != FALSE;
}
My application is crashing. I think its due to some missing windows dll for the operations performed. Is there any other way to perform the same operation using Qt alone?
Roku have already told your problem in manipulating with QString and wchar_t*.
See the documentation: QString Class Reference, method toWCharArray:
int QString::toWCharArray ( wchar_t * array ) const
Fills the array with the data contained in this QString object. The array is encoded in utf16 on platforms where wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms where wchar_t is 4 bytes wide (most Unix systems).
array has to be allocated by the caller and contain enough space to hold the complete string (allocating the array with the same length as the string is always sufficient).
returns the actual length of the string in array.
If you are simply looking for a way to remove a file using Qt, use QFile::remove:
QFile file(fileNameStr);
file.remove(); // Returns a bool; true if successful
If you want Qt to manage the entire life cycle of a temporary file for you, take a look at QTemporaryFile:
QTemporaryFile tempFile(fileName);
if (tempFile.open())
{
// Do stuff with file here
}
// When tempFile falls out of scope, it is automatically deleted.

Windows fopen and the N flag

I'm reading some code that uses fopen to open files for writing. The code needs to be able to close and rename these files from time to time (it's a rotating file logger). The author says that for this to happen the child processes must not inherit these FILE handles. (On Windows, that is; on Unix it's OK.) So the author writes a special subroutine that duplicates the handle as non-inheritable and closes the original handle:
if (!(log->file = fopen(log->path, mode)))
return ERROR;
#ifdef _WIN32
sf = _fileno(log->file);
sh = (HANDLE)_get_osfhandle(sf);
if (!DuplicateHandle(GetCurrentProcess(), sh, GetCurrentProcess(),
&th, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
fclose(log->file);
return ERROR;
}
fclose(log->file);
flags = (*mode == 'a') ? _O_APPEND : 0;
tf = _open_osfhandle((intptr_t)th, _O_TEXT | flags);
if (!(log->file = _fdopen(tf, "at"))) {
_close(tf);
return ERROR;
}
#endif
Now, I'm also reading MSDN docs on fopen and see that their version of fopen has a Microsoft-specific flag that seems to do the same: the N flag:
N: Specifies that the file is not inherited by child processes.
Question: do I understand it correctly that I can get rid of that piece above and replace it (on Windows) with an additional N in the mode parameter?
Yes, you can.
fopen("myfile", "rbN") creates a non-inheritable file handle.
The N flag is not mentioned anywhere in Linux documentation for fopen, so the solution will be most probably not portable, but for MS VC it works fine.

How to copy struct file?

I'm porting old linux kernel code for newer version 2.6.32.
There is a part that copies a file descriptor. The idea was to allocate a new file descriptor and a new struct file and use them with another f_op and , leaving all other fields of struct file equivalent to original's.
How do I do this in a modern kernel?
I've written an approximate implementation but I don't know whether i should call file_get, path_get or do others use counter incrementation.
struct file * copy_file(const struct file * iOrig, int * oNewFd) {
if (!orig)
return 0;
*oNewFd = get_unused_fd();
if (*oNewFd < 0)
return 0;
struct file * rv = alloc_file(orig->f_path.mnt, orig->f_path.dentry, orig->f_path.mode, orig->f_op);
if (!rv)
goto free_fd;
fd_install(fd, rv);
return rv;
free_fd:
put_unused_fd(*oNewFd)
return 0;
}
P.S. In fact having all fileds of original file copied is not neccessary. I just need to allow a new set of file operations in user-space. So creating a new descriptor owned by current with a given f_op will do.
path_get sounds fine. Check out an example here http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/fs/pipe.c#L1046 and you'll be able to find more refs there if you need them.

Resources