logo       

Re: SmbFile.getDiskFreeSpace bug: msg#00132

network.samba.java

Subject: Re: SmbFile.getDiskFreeSpace bug


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

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() + "]" );
<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise