Solved

Sparse file help!

Posted on 2001-07-10
11
1,141 Views
Last Modified: 2013-12-03
Trying to mark a file as sparse, but keep getting an "Incorrect function" error. Relevant code:

DWORD dwAccess = GENERIC_WRITE;
m_hFile = CreateFile(m_strFilename,
                     dwAccess,
                     0,     // Exclusive access
                     NULL,
                     dwCreateFlag,
                     FILE_ATTRIBUTE_NORMAL,
                     NULL );

if( m_hFile == (HANDLE) INVALID_HANDLE_VALUE )
{
     RETURN_FILE_ERROR(_T("Unable to create Cache file"));
}

DWORD dwBytesReturned = 0;
QCHECK_RETURN( DeviceIoControl(
     m_hFile,            // handle to a file
     FSCTL_SET_SPARSE,   // dwIoControlCode operation
     NULL,               // lpInBuffer; must be NULL
     0,                  // nInBufferSize; must be zero
     NULL,               // lpOutBuffer; must be NULL
     0,                  // nOutBufferSize; must be zero
     &dwBytesReturned,   // number of bytes returned
     NULL                // OVERLAPPED structure
     ), E_FAIL );
     
I've tried a number of combinations of flags, to no avail.

The DeviceIoControl code is taken straight from the Platform SDK docs -- what could possibly be going wrong?

I'm on DevStudio sp5, Win2k sp1.


0
Comment
Question by:barrett
  • 5
  • 3
  • 2
  • +1
11 Comments
 
LVL 5

Expert Comment

by:robpitt
ID: 6270497
Never used it but it looks okay.
It is running on 2000 with NTFS, yes?

Rob
0
 

Author Comment

by:barrett
ID: 6270516
Yes, Win2k sp1 with NTFS. Can't find any documentation on the "incorrect function" error with sparse files.
0
 
LVL 5

Expert Comment

by:robpitt
ID: 6270905
Maybe for some unknown reason your NTFS doesn't support spare files. The only reason I can think of is because maybe the NTFS drive is marked as version 4 or maybe theres some system setting that inhibits use of sparse files - I don't know.

PS Does GetVolumeInformation() return the FILE_SUPPORTS_SPARSE_FILES flag?
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:barrett
ID: 6271122
It appears the volume supports sparse files:

TCHAR tzRootDir[MAX_PATH] = _T( "D:\\" );
TCHAR tzVolumeName[MAX_PATH] = _T( "\0" );
TCHAR tzFileSystemNameBuffer[MAX_PATH] = _T( "\0" );

DWORD dwFileSystemFlags = 0;
DWORD dwMaximumComponentLength = 0;
BOOL bRetVal = GetVolumeInformation(
     tzRootDir,                 // root directory
     tzVolumeName,              // volume name buffer
     MAX_PATH,                  // length of name buffer
     NULL,                      // volume serial number
     &dwMaximumComponentLength, // maximum file name length
     &dwFileSystemFlags,        // file system options
     tzFileSystemNameBuffer,    // file system name buffer
     MAX_PATH                   // length of file system name buffer
     );

ATLASSERT( dwFileSystemFlags & 0x000700ff );

This assertion succeeds, and tzFileSystemNameBuffer holds "NTFS".

0
 

Author Comment

by:barrett
ID: 6271126
er, that assertion should read:

ATLASSERT( dwFileSystemFlags & FILE_SUPPORTS_SPARSE_FILES );

The value of dwFileSystemFlags is 0x000700ff.
0
 

Author Comment

by:barrett
ID: 6271419
INterestingly, the code straight out of MSDN fails the same way:

HANDLE h = CreateFile("A huge file.txt",
   GENERIC_WRITE, 0, NULL,
   CREATE_ALWAYS, 0, NULL);
DWORD dw;
DeviceIoControl(h, FSCTL_SET_SPARSE, NULL,
   0, NULL, 0, &dw, NULL);
LONG lDist = 8;   // 32 GB!!!
SetFilePointer(h, 0, &lDist, FILE_BEGIN);
SetEndOfFile(h);
CloseHandle(h);

So something must be wrong with my configuration. Haven't a clue what it could be.


0
 
LVL 15

Accepted Solution

by:
NickRepin earned 200 total points
ID: 6272525
This code works perfectly, the file created is 1.5M in size, the actual size on the disk is 500K.

#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <winioctl.h>
#include <iostream.h>

void main(int argc,char* argv[])
{        
   if(argc<2)
   {
      cout<<"Usage: sparse  <drive_letter>"<<endl;
      return;
   }
   
   char buf[MAX_PATH]="G:\\\0est_sparse";
   buf[0]=argv[1][0];

   DWORD flags;
   if(!GetVolumeInformation(buf,0,0,0,0,&flags,0,0))
   {
      cout<<"Cannot GetVolumeInformation"<<endl;
      return;
   }

   cout<<"flags="<<hex<<flags<<dec<<endl;
   if(!(flags & FILE_SUPPORTS_SPARSE_FILES))
   {
      cout<<"Sparse files are not supported"<<endl;
   //   return;
   }

   buf[3]='t';
   cout<<buf<<endl;
   HANDLE hFile=CreateFile(buf,
      GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0);
   if(hFile==INVALID_HANDLE_VALUE)
   {
      cout<<"Cannot create file "<<endl;
      return;
   }

   SetFilePointer(hFile,1500000,0,FILE_BEGIN);
   SetEndOfFile(hFile);


   DWORD dwBytesReturned = 0;
   if(!DeviceIoControl(hFile,FSCTL_SET_SPARSE,
      0,0,0,0,&dwBytesReturned,0))
   {
      cout<<"Cannot set sparce "<<GetLastError()<<endl;
      CloseHandle(hFile);
      return;
   }

   FILE_ZERO_DATA_INFORMATION zdi;
   zdi.FileOffset.LowPart=0;
   zdi.FileOffset.HighPart=0;
   zdi.BeyondFinalZero.LowPart=1000000;
   zdi.BeyondFinalZero.HighPart=0;
   if(!DeviceIoControl(hFile,FSCTL_SET_ZERO_DATA,
      &zdi,sizeof(zdi),0,0,&dwBytesReturned,0))
   {
      cout<<"Cannot zero data "<<GetLastError()<<endl;
      CloseHandle(hFile);
      return;
   }

   CloseHandle(hFile);
}

0
 
LVL 15

Expert Comment

by:NickRepin
ID: 6272536
I do not know what is QCHECK_RETURN(..., E_FAIL )

But I'm pretty sure that E_FAIL is 0x80004005L, which is neither TRUE nor FALSE.
0
 

Author Comment

by:barrett
ID: 6273249

Unfortunately this code fails the same way on both of my machines, "Incorrect function". This really is Win2k sp1 with an NTFS volume. What could possibly be going wrong?

I shouldn't have included that QCHECK_RETURN macro -- it's part of our shop's error-handling framework. Doesn't affect this test.
0
 
LVL 5

Expert Comment

by:robpitt
ID: 6273507
I give up!

You just seem to have a "special" machine that just will not let you use sparse files despite the fact that it should let you.
0
 

Expert Comment

by:geplauder
ID: 8114282
the same effect took me hours today.
A hint was "IOCTL: 0x980C4" from sysinternal's "File Monitor", where "fsutil sparse setflag" would just work.
I checked with winIOCTL.h (24APR98), which contains
#define FILE_DEVICE_FILE_SYSTEM         0x00000009
#define CTL_CODE(DeviceType, Function, Method, Access) \
    ((DeviceType)<<16) | ((Access)<<14) | ((Function)<<2) | (Method))
#define METHOD_BUFFERED                 0
#define FILE_WRITE_ACCESS         ( 0x0002 )    // file & pipe
#define FSCTL_SET_SPARSE                CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA)
giving the value above. I guessed DeviceType and Function were above suspicion, so I fiddled with access and method:
a "control code" of 0x900c4 seems to work fine. This corresponds to "FILE_ANY_ACCESS", I found "FILE_ACCESS_SPECIAL" with cygwin. I spent hours trying to track down english and german versions of VS6 & service packs: the english VS contains the same definitions, no service pack I ran into any winIOCTL.h at all. google found the above digit sequence in proximity with FSCTL_SET_SPARSE and VB. Is this one of those non-existant cases where installing a current service pack does not take you to the same state as installing all of them sequentially?
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

790 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question