|
Re: SmbFile.getDiskFreeSpace bug: msg#00130network.samba.java
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. Thomas Thomas Krammer said: 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.203125000 +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 13:21:28.984375000 +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; } @@ -130,6 +133,38 @@ return bufferIndex - start; } + int readFsFullSizeInformationWireFormat( byte[] buffer, int bufferIndex ) + { + int start = bufferIndex; + + SmbInfoAllocation info = new SmbInfoAllocation(); + + // Read total allocation units. + info.alloc = readInt4( buffer, bufferIndex ); + bufferIndex += 4; + info.alloc |= readInt4( buffer, bufferIndex ) << 32L; + bufferIndex += 4; + + // read caller available allocation units + info.free = readInt4( buffer, bufferIndex ); + bufferIndex += 4; + info.free |= readInt4( buffer, bufferIndex ) << 32L; + bufferIndex += 4; + + // skip actual free units + bufferIndex += 8; + + info.sectPerAlloc = readInt4( buffer, bufferIndex ); + bufferIndex += 4; + + info.bytesPerSect = readInt4( buffer, bufferIndex ); + bufferIndex += 4; + + this.info = info; + + return bufferIndex - start; + } + public String toString() { return new String( "Trans2QueryFSInformationResponse[" + super.toString() + "]" ); |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | soft zmfeklf: 00130, Luther Stanley |
|---|---|
| Next by Date: | Re: Batching command in CIFS: 00130, Cellina Lin |
| Previous by Thread: | Re: SmbFile.getDiskFreeSpace bugi: 00130, Michael B Allen |
| Next by Thread: | Re: SmbFile.getDiskFreeSpace bug: 00130, Thomas Krammer |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |