From: djberg96@... (Daniel Berger) Date: 2004-11-13T08:13:26+09:00 Subject: Win32, file descriptors and rb_io_check_writable() Hi all, Windows 2000/XP VC++ 6.0 or 7.0 Ruby 1.8.2 (Installer RC9) I'm trying to write an extension for the win32-file package. Specifically, I want to write a wrapper for CreateFile() called File.nopen (for 'native open'). I thought this would be nice for two reasons. First, it would give you finer control over HANDLE creation on the Win32 platform. Second, it would allow you to open directories, since you cannot currently call File.open on a directory on Windows. So, the API would look like this: File.nopen(file, access, share, creation, flags) The underlying C code looks like this: static VALUE file_nopen(int argc, VALUE *argv, VALUE klass){ HANDLE h; int rv; VALUE args[1]; VALUE rbFile, rbAccess, rbShare, rbCreation, rbFlags; DWORD dwAccess = FILE_ALL_ACCESS; // I tried various flags here DWORD dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE; DWORD dwCreation = OPEN_EXISTING; DWORD dwFlags = FILE_ATTRIBUTE_NORMAL; rb_scan_args(argc,argv,"14",&rbFile,&rbAccess,&rbShare,&rbCreation,&rbFlags); // Override default values with user supplied values if(Qnil != rbAccess) dwAccess = (DWORD)NUM2UINT(rbAccess); if(Qnil != rbShare) dwShare = (DWORD)NUM2UINT(rbShare); if(Qnil != rbCreation) dwCreation = (DWORD)NUM2UINT(rbCreation); if(Qnil != rbFlags) dwFlags = (DWORD)NUM2UINT(rbFlags); h = CreateFile( StringValuePtr(rbFile), dwAccess, dwShare, NULL, // Cannot be inherited dwCreation, dwFlags, NULL // No template ); if(h == INVALID_HANDLE_VALUE) rb_raise(cFileError,ErrorDescription(GetLastError())); // Convert HANDLE to file descriptor args[0] = UINT2NUM(_open_osfhandle((long)h,O_RDWR)); // Return a bonafide File object, based on the file descriptor return rb_class_new_instance(1,args,rb_cFile); } For read operations, this works. I can do this: fh = File.nopen("C:\\somefile") p fh.readlines # works fine fh.close I can even read from a directory: fh = File.nopen("C:\\TESTDIR",nil,nil,nil,File::BACKUP_SEMANTICS) fh.close But, I cannot write to the filehandle: fh = File.nopen("C:\\somefile") fh.puts "Hello" test.rb:13:in `write': not opened for writing (IOError) from test.rb:13:in `puts' from test.rb:13 That error appears to be coming from the rb_io_check_writable() function, which in turn is checking the mode of the OpenFile struct defined in rubyio.h. How do I deal with this? Am I doing something wrong? Or would it take a modification of io.c for this to work? If so, what should be done? Regards, Dan