[jcifs] SmbFile.getDiskFreeSpace bug
Thomas Krammer
tkrammer at nxn-software.com
Thu Jan 27 20:47:51 GMT 2005
> The Windows Explorer is reporting the correct value. Windows XP is
> using information level 1007 instead of information level 1 which
> JCIFS uses. According the the Samba sources this is
>
> #define SMB_FS_FULL_SIZE_INFORMATION 1007
>
> It returns the following information (see trans2.c in the Samba sources):
>
> int64 Total allocation units
> int64 Caller available allocation units
> int64 Actual available allocation units
> int32 Sectors per allocation unit
> int32 Bytes per sector
>
> So it returns the block counts as 64 bit integers instead of 32 bit
> integers.
>
> I extended getDiskFreeSpace() to use SMB_FS_FULL_SIZE_INFORMATION. If
> the server returns a NT_STATUS_INVALID_INFO_CLASS error I fall back to
> SMB_INFO_ALLOCATION. I don't know if there is a way to know if the
> server supports a certain information level before making the call.
>
> I attached a patch with my extensions. I did some limited testing
> against a Windows 2003 Server and it seems to work fine. I also asked
> our customer to try out the patched JCIFS library. I will report back
> as soon as I hear from them.
>
Of course it didn't work on their machine...
I just copied the int64 handling from
Trans2QueryFSInformationResponse.readSmbQueryFSSizeInfoWireFormat().
That code doesn't work when actually more than 32 bit of the int64 are used.
I'm now using readInt8() and it works fine. I also fixed
readSmbQueryFSSizeInfoWireFormat(). I attached the fixed version of the
patch.
Thomas
-------------- next part --------------
diff -Naur jcifs_1.1.7_org/src/jcifs/smb/SmbFile.java jcifs_1.1.7/src/jcifs/smb/SmbFile.java
--- jcifs_1.1.7_org/src/jcifs/smb/SmbFile.java 2005-01-16 18:55:22.000000000 +0100
+++ jcifs_1.1.7/src/jcifs/smb/SmbFile.java 2005-01-27 14:03:50.203000000 +0100
@@ -2183,21 +2183,35 @@
*/
public long getDiskFreeSpace() throws SmbException {
if( getType() == TYPE_SHARE || type == TYPE_FILESYSTEM ) {
- Trans2QueryFSInformationResponse response;
- int level = Trans2QueryFSInformationResponse.SMB_INFO_ALLOCATION;
-
- response = new Trans2QueryFSInformationResponse( level );
- sendTransaction( new Trans2QueryFSInformation( level ), response );
-
- if( type == TYPE_SHARE ) {
- size = response.info.getCapacity();
- sizeExpiration = System.currentTimeMillis() + attrExpirationPeriod;
+ try {
+ return queryFSInformation(Trans2QueryFSInformationResponse.SMB_FS_FULL_SIZE_INFORMATION);
}
-
- return response.info.getFree();
+ catch(SmbException ex) {
+ if(ex.getNtStatus() == NtStatus.NT_STATUS_INVALID_INFO_CLASS) {
+ // SMB_FS_FULL_SIZE_INFORMATION not supported by the server.
+ return queryFSInformation(Trans2QueryFSInformationResponse.SMB_INFO_ALLOCATION);
+ }
+
+ throw ex;
+ }
+
}
return 0L;
}
+
+ private long queryFSInformation( int level ) throws SmbException {
+ Trans2QueryFSInformationResponse response;
+
+ response = new Trans2QueryFSInformationResponse( level );
+ sendTransaction( new Trans2QueryFSInformation( level ), response );
+
+ if( type == TYPE_SHARE ) {
+ size = response.info.getCapacity();
+ sizeExpiration = System.currentTimeMillis() + attrExpirationPeriod;
+ }
+
+ return response.info.getFree();
+ }
/**
* Creates a directory with the path specified by this
diff -Naur jcifs_1.1.7_org/src/jcifs/smb/Trans2QueryFSInformationResponse.java jcifs_1.1.7/src/jcifs/smb/Trans2QueryFSInformationResponse.java
--- jcifs_1.1.7_org/src/jcifs/smb/Trans2QueryFSInformationResponse.java 2005-01-16 18:55:22.000000000 +0100
+++ jcifs_1.1.7/src/jcifs/smb/Trans2QueryFSInformationResponse.java 2005-01-27 21:09:10.453125000 +0100
@@ -25,6 +25,7 @@
// information levels
static final int SMB_INFO_ALLOCATION = 1;
static final int SMB_QUERY_FS_SIZE_INFO = 0x103;
+ static final int SMB_FS_FULL_SIZE_INFORMATION = 1007;
class SmbInfoAllocation implements AllocInfo {
long alloc; // Also handles SmbQueryFSSizeInfo
@@ -77,6 +78,8 @@
return readSmbInfoAllocationWireFormat( buffer, bufferIndex );
case SMB_QUERY_FS_SIZE_INFO:
return readSmbQueryFSSizeInfoWireFormat( buffer, bufferIndex );
+ case SMB_FS_FULL_SIZE_INFORMATION:
+ return readFsFullSizeInformationWireFormat( buffer, bufferIndex );
default:
return 0;
}
@@ -110,19 +113,42 @@
SmbInfoAllocation info = new SmbInfoAllocation();
- info.alloc = readInt4( buffer, bufferIndex );
- bufferIndex += 4;
- info.alloc |= readInt4( buffer, bufferIndex ) << 32L;
- bufferIndex += 4;
+ info.alloc = readInt8( buffer, bufferIndex );
+ bufferIndex += 8;
- info.free = readInt4( buffer, bufferIndex );
+ info.free = readInt8( buffer, bufferIndex );
+ bufferIndex += 8;
+
+ info.sectPerAlloc = readInt4( buffer, bufferIndex );
bufferIndex += 4;
- info.free |= readInt4( buffer, bufferIndex ) << 32L;
+
+ info.bytesPerSect = readInt4( buffer, bufferIndex );
bufferIndex += 4;
+ this.info = info;
+
+ return bufferIndex - start;
+ }
+ int readFsFullSizeInformationWireFormat( byte[] buffer, int bufferIndex )
+ {
+ int start = bufferIndex;
+
+ SmbInfoAllocation info = new SmbInfoAllocation();
+
+ // Read total allocation units.
+ info.alloc = readInt8( buffer, bufferIndex );
+ bufferIndex += 8;
+
+ // read caller available allocation units
+ info.free = readInt8( buffer, bufferIndex );
+ bufferIndex += 8;
+
+ // skip actual free units
+ bufferIndex += 8;
+
info.sectPerAlloc = readInt4( buffer, bufferIndex );
bufferIndex += 4;
-
+
info.bytesPerSect = readInt4( buffer, bufferIndex );
bufferIndex += 4;
@@ -130,6 +156,7 @@
return bufferIndex - start;
}
+
public String toString() {
return new String( "Trans2QueryFSInformationResponse[" +
super.toString() + "]" );
More information about the jcifs
mailing list