12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237 |
- /*
- * Copyright (C) 2006-2010 Alfresco Software Limited.
- *
- * This file is part of Alfresco
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
- */
- package org.alfresco.jlan.client;
- import java.io.*;
- import java.util.*;
- import org.alfresco.jlan.client.info.DeviceAttributesInfo;
- import org.alfresco.jlan.client.info.DeviceInfo;
- import org.alfresco.jlan.client.info.DiskInfo;
- import org.alfresco.jlan.client.info.FileInfo;
- import org.alfresco.jlan.client.info.VolumeInfo;
- import org.alfresco.jlan.client.smb.DirectoryWatcher;
- import org.alfresco.jlan.server.filesys.AccessMode;
- import org.alfresco.jlan.server.filesys.FileAction;
- import org.alfresco.jlan.server.filesys.FileAttribute;
- import org.alfresco.jlan.smb.DataType;
- import org.alfresco.jlan.smb.Dialect;
- import org.alfresco.jlan.smb.FileInfoLevel;
- import org.alfresco.jlan.smb.LockingAndX;
- import org.alfresco.jlan.smb.NTTime;
- import org.alfresco.jlan.smb.OpLock;
- import org.alfresco.jlan.smb.PCShare;
- import org.alfresco.jlan.smb.PacketType;
- import org.alfresco.jlan.smb.SMBException;
- import org.alfresco.jlan.smb.SMBStatus;
- import org.alfresco.jlan.smb.SharingMode;
- import org.alfresco.jlan.smb.TransactBuffer;
- import org.alfresco.jlan.smb.WinNT;
- import org.alfresco.jlan.smb.nt.LoadException;
- import org.alfresco.jlan.smb.nt.SaveException;
- import org.alfresco.jlan.smb.nt.SecurityDescriptor;
- import org.alfresco.jlan.smb.nt.SymLink;
- import org.alfresco.jlan.util.DataBuffer;
- import org.alfresco.jlan.util.DataPacker;
- import org.alfresco.jlan.smb.nt.NTIOCtl;
- /**
- * SMB CIFS disk session class
- *
- * <p>
- * The CIFSDiskSession class extends the DiskSession class and provides CIFS protocol specific
- * implementations for the DiskSession methods.
- *
- * <p>
- * An CIFSDiskSession object will be created by the SessionFactory static class when the negotiated
- * SMB dialect indicates that the remote server supports an SMB dialect greater than Core or
- * CorePlus.
- *
- * <p>
- * The SessionFactory.OpenDisk() method is used to create a session to a remote disk share. A
- * PCShare object specifies the remote server and share to connect to, along with any required
- * access control.
- *
- * @author gkspencer
- */
- public final class CIFSDiskSession extends DiskSession {
- // Constants
- //
- // SMB session keep-alive interval
- private final static long SessionKeepAlive = 60000L;
- // List of pending asynchronous requests
- private List<AsynchRequest> m_asynchRequests;
- // List of open files with an oplock
-
- private HashMap<Integer, CIFSFile> m_oplockFiles;
-
- /**
- * Class constructor
- *
- * @param shr Remote server details.
- * @param dialect SMB dialect that this session is using
- */
- protected CIFSDiskSession(PCShare shr, int dialect) {
- super(shr, dialect);
- }
- /**
- * Close this connection with the remote server share.
- *
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public void CloseSession()
- throws java.io.IOException, SMBException {
- // Build a tree disconnect packet
- m_pkt.setCommand(PacketType.TreeDisconnect);
- m_pkt.setUserId(getUserId());
- m_pkt.setTreeId(m_treeid);
- m_pkt.setParameterCount(0);
- m_pkt.setByteCount(0);
- // Send the tree disconnect packet
- m_pkt.ExchangeSMB(this, m_pkt);
- // Indicate that the session has been closed
- m_treeid = DiskSession.Closed;
- // Close the network session
- super.CloseSession();
- }
- /**
- * Create a new directory on the remote file server.
- *
- * @param dir Directory name string. If the directory name does not have a leading '\' the
- * current working directory for this session will be prepended to the string.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final void CreateDirectory(String dir)
- throws java.io.IOException, SMBException {
- // Build the new path
- String newPath = dir;
- if ( newPath.startsWith("\\") == false)
- newPath = PCShare.makePath(getWorkingDirectory(), dir);
- // Pre-NT dialect create directory
- if ( getDialect() != Dialect.NT || isUnicode() == false) {
- // Create an SMB create directory packet
- m_pkt.setCommand(PacketType.CreateDirectory);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setParameterCount(0);
- // Copy the directory name data block to the SMB packet
- m_pkt.resetBytePointer();
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString(newPath, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the SMB create directory packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- }
- else {
- // Use the NTCreateAndX SMB to create the directory
- CIFSFile dirFile = NTCreate(newPath, AccessMode.NTRead, FileAttribute.NTDirectory, SharingMode.READWRITE,
- FileAction.NTCreate, 0, WinNT.CreateDirectory);
- // Close the directory file
- dirFile.Close();
- }
- }
- /**
- * Create and open a file on the remote file server.
- *
- * @param fname Remote file name string.
- * @return SMBFile for the opened file, else null.
- * @exception java.io.IOException If an I/O error occurs
- * @exception SMBException If an SMB error occurs
- */
- public final SMBFile CreateFile(String fname)
- throws java.io.IOException, SMBException {
- // Create a new file
- return OpenFile(fname, AccessMode.WriteOnly);
- }
- /**
- * Delete the specified directory on the remote file server.
- *
- * @param dir Directory name string. If the directory name does not have a leading '\' the
- * current working directory for this session will be preprended to the string.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final void DeleteDirectory(String dir)
- throws java.io.IOException, SMBException {
- // Create an SMB delete directory packet
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setCommand(PacketType.DeleteDirectory);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setParameterCount(0);
- // Check if the directory name contains a path
- String delPath = dir;
- if ( delPath.startsWith("\\") == false)
- delPath = PCShare.makePath(getWorkingDirectory(), dir);
- // Pack the path to be deleted
- m_pkt.resetBytePointer();
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString(delPath, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the SMB delete directory packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- }
- /**
- * Delete the specified file on the remote file server.
- *
- * @param fname File name of the remote file to delete. If the file name does not have a leading
- * '\' the current working directory for this session will be prepended to the
- * string.
- * @param attr File attributes of the file(s) to delete.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final void DeleteFile(String fname, int attr)
- throws java.io.IOException, SMBException {
- // Create an SMB delete file packet
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setCommand(PacketType.DeleteFile);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setParameterCount(1);
- m_pkt.setParameter(0, attr);
- // Check if the file name contains a path
- String delName = fname;
- if ( delName.startsWith("\\") == false)
- delName = PCShare.makePath(getWorkingDirectory(), fname);
- // Copy the file name data block to the SMB packet
- m_pkt.resetBytePointer();
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString(delName, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the SMB delete file packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- }
- /**
- * Get disk information for this remote disk.
- *
- * @return Disk information object, or null.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final DiskInfo getDiskInformation()
- throws java.io.IOException, SMBException {
- // Check if the NT dialect has been negotiated, or LanMan
- if ( this.getDialect() != Dialect.NT) {
- // Create a query disk information SMB packet
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setCommand(PacketType.DiskInformation);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setParameterCount(0);
- m_pkt.setByteCount(0);
- // Send/receive the SMB file information packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- // Extract the disk information from the received SMB packet
- int totunit = m_pkt.getParameter(0);
- int blkperunit = m_pkt.getParameter(1);
- int blksize = m_pkt.getParameter(2);
- int freeblk = m_pkt.getParameter(3);
- // Create a disk information object
- return new DiskInfo(getPCShare(), totunit, blkperunit, blksize, freeblk);
- }
- else {
- // Create the transaction request
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFileSys, null, 0, 2, 0);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(FileInfoLevel.FSInfoQuerySize);
- // Perform the get file system information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
- // Unpack the response data
- DiskInfo dinfo = null;
- if ( respBuf != null && respBuf.hasDataBuffer()) {
- // Unpack the file system information
- DataBuffer dataBuf = respBuf.getDataBuffer();
- long fsTotalUnit = dataBuf.getLong();
- long fsAvailUnit = dataBuf.getLong();
- int fsSectorsPerUnit = dataBuf.getInt();
- int fsBytesPerSector = dataBuf.getInt();
- // Create the disk information details
- dinfo = new DiskInfo(getPCShare(), fsTotalUnit, fsSectorsPerUnit, fsBytesPerSector, fsAvailUnit);
- }
- // Return the disk information
- return dinfo;
- }
- }
- /**
- * Get file information for the specified file.
- *
- * @param fname File name of the file to return information for.
- * @see org.alfresco.jlan.smb.FileInfoLevel
- * @param level Information level required
- * @return FileInfo if the request was successful, else null.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception java.io.FileNotFoundException If the remote file does not exist.
- * @exception SMBException If an SMB level error occurs
- */
- public final FileInfo getFileInformation(String fname, int level)
- throws java.io.IOException, java.io.FileNotFoundException, SMBException {
- // Build the file name/path string
- String pathName = fname;
- if ( pathName.startsWith("\\") == false)
- pathName = PCShare.makePath(getWorkingDirectory(), fname);
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryPath, null, 0, 512, 0);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(level);
- paramBuf.putInt(0);
- paramBuf.putString(pathName, isUnicode());
- // Perform the get file information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
- // Unpack the received file information data
- FileInfo finfo = null;
- if ( respBuf != null && respBuf.hasDataBuffer()) {
- // Unpack the file information
- DataBuffer buf = respBuf.getDataBuffer();
- switch (level) {
- case FileInfoLevel.PathStandard:
- finfo = FileInfoPacker.unpackFileInfoStandard("", buf, false);
- break;
- case FileInfoLevel.PathQueryEASize:
- finfo = FileInfoPacker.unpackFileInfoStandard("", buf, true);
- break;
- case FileInfoLevel.PathAllEAs:
- finfo = FileInfoPacker.unpackQueryAllEAs("", buf);
- break;
- case FileInfoLevel.PathFileBasicInfo:
- finfo = FileInfoPacker.unpackQueryBasicInfo("", buf);
- break;
- case FileInfoLevel.PathFileStandardInfo:
- finfo = FileInfoPacker.unpackQueryStandardInfo("", buf);
- break;
- case FileInfoLevel.PathFileEAInfo:
- finfo = FileInfoPacker.unpackQueryEAInfo("", buf);
- break;
- case FileInfoLevel.PathFileNameInfo:
- finfo = FileInfoPacker.unpackQueryNameInfo(buf, respBuf.isUnicode());
- break;
- case FileInfoLevel.PathFileAllInfo:
- finfo = FileInfoPacker.unpackQueryAllInfo(buf, respBuf.isUnicode());
- break;
- case FileInfoLevel.PathFileAltNameInfo:
- finfo = FileInfoPacker.unpackQueryNameInfo(buf, respBuf.isUnicode());
- break;
- case FileInfoLevel.PathFileStreamInfo:
- finfo = FileInfoPacker.unpackQueryStreamInfo("", buf, respBuf.isUnicode());
- break;
- case FileInfoLevel.PathFileCompressionInfo:
- finfo = FileInfoPacker.unpackQueryCompressionInfo("", buf);
- break;
- }
- }
- // Return the file information
- return finfo;
- }
- /**
- * Get the disk volume information
- *
- * @return VolumeInfo, or null
- * @exception java.io.IOException If an I/O error occurs
- * @exception SMBException If an SMB level error occurs
- */
- public final VolumeInfo getVolumeInformation()
- throws java.io.IOException, SMBException {
- // Check if the NT dialect has been negotiated, or LanMan
- VolumeInfo volInfo = null;
- if ( this.getDialect() != Dialect.NT) {
- // Build the search request
- m_pkt.setCommand(PacketType.Search);
- m_pkt.setUserId(getUserId());
- m_pkt.setTreeId(getTreeId());
- // Initialize the search SMB packet
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setParameterCount(2);
- m_pkt.setParameter(0, 1); // number of directory entries to return
- m_pkt.setParameter(1, FileAttribute.Volume);
- // Pack the search string
- m_pkt.resetBytePointer();
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString("", false);
- // Append a null resume key, to indicate the start of a new search
- m_pkt.packByte(DataType.VariableBlock);
- m_pkt.packWord(0);
- m_pkt.setByteCount();
- // Send/receive the search SMB packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- // Unpack the volume label
- m_pkt.resetBytePointer();
- m_pkt.skipBytes(33); // data type byte + length word + offset to file name/volume label
- String label = m_pkt.unpackString(m_pkt.isUnicode());
- // Create the volume information object
- volInfo = new VolumeInfo(label);
- }
- else {
- // Create the transaction request
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFileSys, null, 0, 2, 0);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(FileInfoLevel.FSInfoQueryVolume);
- // Perform the get file system information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
- // Unpack the volume information
- if ( respBuf != null && respBuf.hasDataBuffer()) {
- // Get the data buffer
- DataBuffer dataBuf = respBuf.getDataBuffer();
- // Get the volume information
- long createTime = dataBuf.getLong();
- int serNo = dataBuf.getInt();
- int nameLen = dataBuf.getInt();
- if ( respBuf.isUnicode())
- nameLen = nameLen / 2;
- dataBuf.skipBytes(2);
- String label = dataBuf.getString(nameLen, respBuf.isUnicode());
- // Create the volume information
- volInfo = new VolumeInfo(label, serNo, NTTime.toSMBDate(createTime));
- }
- }
- // Return the volume information
- return volInfo;
- }
- /**
- * Check if the specified file name is a directory.
- *
- * @param dir Directory name string. If the directory name does not have a leading '\' the
- * current working directory for this session will be preprended to the string.
- * @return true if the specified file name is a directory, else false.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final boolean isDirectory(String dir)
- throws java.io.IOException, SMBException {
- // Allocate an SMB packet for the check directory request
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setCommand(PacketType.CheckDirectory);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setParameterCount(0);
- // Build the remote directory tree relative path
- String pathName = dir;
- if ( pathName.startsWith("\\") == false)
- pathName = PCShare.makePath(getWorkingDirectory(), dir);
- // Pack the directory name
- m_pkt.resetBytePointer();
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString(pathName, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the SMB check directory packet
- m_pkt.ExchangeSMB(this, m_pkt);
- // Check if a valid response was received, indicates the path is a directory
- return m_pkt.isValidResponse();
- }
- /**
- * Open a file on the remote file server.
- *
- * @param fname Remote file name string.
- * @param flags File open option flags.
- * @return SMBFile for the opened file, else null.
- * @exception java.io.IOException If an I/O error occurs
- * @exception SMBException If an SMB level error occurs
- */
- public final SMBFile OpenFile(String fname, int flags)
- throws java.io.IOException, SMBException {
- // Check if the path is a valid file path
- if ( isValidFilePath(fname) == false)
- throw new SMBException(SMBStatus.NTErr, SMBStatus.NTInvalidParameter);
- // Build the file name details
- String fileName = fname;
- if ( fileName.startsWith("\\") == false)
- fileName = PCShare.makePath(getWorkingDirectory(), fname);
- // Pre-NT dialect open file
- if ( getDialect() != Dialect.NT || isUnicode() == false) {
- // Initialize the SMB request to open an existing file
- m_pkt.setCommand(PacketType.OpenAndX);
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- // Set the parameter words
- m_pkt.setParameterCount(15);
- m_pkt.setAndXCommand(0xFF); // no secondary command
- m_pkt.setParameter(1, 0); // offset to next command
- m_pkt.setParameter(2, 0x01); // return additional information
- m_pkt.setParameter(3, flags);
- m_pkt.setParameter(4, 0); // normal files only for now
- m_pkt.setParameter(5, 0); // file attributes
- m_pkt.setParameter(6, 0); // creation time
- m_pkt.setParameter(7, 0); // creation date
- // Default open mode is 'open if file exists'
- int openMode = FileAction.OpenIfExists;
- if ( AccessMode.getAccessMode(flags) == AccessMode.WriteOnly) {
- // Truncate the file if it exists, create file if it does not exist
- openMode = FileAction.CreateNotExist + FileAction.TruncateExisting;
- }
- else if ( AccessMode.getAccessMode(flags) == AccessMode.ReadWrite) {
- // Open the file if it exists, create the file if it does not exist
- openMode = FileAction.CreateNotExist + FileAction.OpenIfExists;
- }
- m_pkt.setParameter(8, openMode);
- m_pkt.setParameter(9, 0); // default allocation on create/truncate (long)
- m_pkt.setParameter(10, 0); // ... high word
- m_pkt.setParameter(11, 0);
- m_pkt.setParameter(12, 0);
- m_pkt.setParameter(13, 0);
- m_pkt.setParameter(14, 0);
- // Pack the file name string
- m_pkt.resetBytePointer();
- m_pkt.packString(fileName, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the SMB file open packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- // Extract the file information from the received SMB packet
- int fid = m_pkt.getParameter(2);
- int attr = m_pkt.getParameter(3);
- int fsiz = (m_pkt.getParameter(7) << 16) + m_pkt.getParameter(6);
- // Create a file information object
- FileInfo finfo = new FileInfo(fname, fsiz, attr);
- // Create an SMB file object
- return new CIFSFile(this, finfo, fid);
- }
- else {
- // Default open mode is 'open if file exists'
- int openMode = FileAction.NTOpen;
- int accessMode = AccessMode.NTRead;
- if ( AccessMode.getAccessMode(flags) == AccessMode.WriteOnly) {
- // Truncate the file if it exists, create file if it does not exist
- openMode = FileAction.NTOverwriteIf;
- accessMode = AccessMode.NTWrite;
- }
- else if ( AccessMode.getAccessMode(flags) == AccessMode.ReadWrite) {
- // Open the file if it exists, create the file if it does not exist
- openMode = FileAction.NTOpenIf;
- accessMode = AccessMode.NTReadWrite;
- }
- // Open the remote file
- return NTCreate(fileName, accessMode, FileAttribute.NTNormal, SharingMode.READWRITEDELETE, openMode, 0, WinNT.CreateFile);
- }
- }
- /**
- * Rename a file, or set of files, on the remote file server.
- *
- * @param curnam Current file name string, may contain wildcards. If the path does not start
- * with a '\' the current working directory string will be preprended.
- * @param newnam New file name.
- * @param attr Search attributes, to determine which file(s) to rename.
- * @see org.alfresco.jlan.server.filesys.FileAttribute
- * @return true if the file rename request was successful, else false.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final boolean RenameFile(String curnam, String newnam, int attr)
- throws java.io.IOException, SMBException {
- // Create an SMB rename packet
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setCommand(PacketType.RenameFile);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setParameterCount(1);
- m_pkt.setParameter(0, attr);
- // Add the current working directory path to the file names if they do not contain a path
- String fromName = curnam;
- if ( fromName.startsWith("\\") == false)
- fromName = PCShare.makePath(getWorkingDirectory(), curnam);
- String toName = newnam;
- if ( toName.startsWith("\\") == false)
- toName = PCShare.makePath(getWorkingDirectory(), newnam);
- // Pack the current and new file names
- m_pkt.resetBytePointer();
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString(fromName, m_pkt.isUnicode());
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString(toName, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the SMB rename file(s) packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- // Check if we got a valid response
- if ( m_pkt.isValidResponse())
- return true;
- // Invalid rename request
- return false;
- }
- /**
- * Set file information for the specified file.
- *
- * @param fname File name of the file to set information for.
- * @param finfo File information containing the new values.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final void setFileInformation(String fname, FileInfo finfo)
- throws java.io.IOException, SMBException {
- // Create an SMB set file information packet
- m_pkt.setCommand(PacketType.SetFileAttributes);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- // Set the call parameters
- m_pkt.setParameterCount(8);
- m_pkt.setParameter(0, finfo.getFileAttributes());
- m_pkt.setParameter(1, finfo.getModifyDateTime().asSMBTime());
- m_pkt.setParameter(2, finfo.getModifyDateTime().asSMBDate());
- for (int i = 3; i < 8; i++)
- m_pkt.setParameter(i, 0);
- // Build the full path string
- String fileName = fname;
- if ( fname.startsWith("\\") == false)
- fileName = PCShare.makePath(getWorkingDirectory(), fname);
- // Pack the file name
- m_pkt.resetBytePointer();
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString(fileName, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the SMB set file information packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- }
- /**
- * Set file information for the specified file, using the file id
- *
- * @param file File to set information for.
- * @param finfo File information containing the new values.
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final void setFileInformation(SMBFile file, FileInfo finfo)
- throws java.io.IOException, SMBException {
- // Create an SMB set file information packet
- m_pkt.setCommand(PacketType.SetInformation2);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- // Set the call parameters
- m_pkt.setParameterCount(7);
- m_pkt.setParameter(0, file.getFileId());
- // Pack the new creation date/time, if available
- if ( finfo.hasCreationDateTime()) {
- m_pkt.setParameter(1, finfo.getCreationDateTime().asSMBTime());
- m_pkt.setParameter(2, finfo.getCreationDateTime().asSMBDate());
- }
- else {
- m_pkt.setParameter(1, 0);
- m_pkt.setParameter(2, 0);
- }
- // Pack the new access date/time, if available
- if ( finfo.hasAccessDateTime()) {
- m_pkt.setParameter(3, finfo.getAccessDateTime().asSMBTime());
- m_pkt.setParameter(4, finfo.getAccessDateTime().asSMBDate());
- }
- else {
- m_pkt.setParameter(3, 0);
- m_pkt.setParameter(4, 0);
- }
- // Pack the new modify date/time, if available
- if ( finfo.hasModifyDateTime()) {
- m_pkt.setParameter(5, finfo.getModifyDateTime().asSMBTime());
- m_pkt.setParameter(6, finfo.getModifyDateTime().asSMBDate());
- }
- else {
- m_pkt.setParameter(5, 0);
- m_pkt.setParameter(6, 0);
- }
- // Clear the byte count
- m_pkt.setByteCount(0);
- // Send/receive the SMB set file information packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- }
- /**
- * Set file attributes for the specified file, using the file name
- *
- * @param fname File name of the file to set information for.
- * @param attrib File attributes mask
- * @see org.alfresco.jlan.server.filesys.FileAttribute
- * @exception java.io.IOException If an I/O error occurs.
- * @exception SMBException If an SMB level error occurs
- */
- public final void setFileAttributes(String fname, int attrib)
- throws java.io.IOException, SMBException {
- // Create an SMB set file information packet
- m_pkt.setCommand(PacketType.SetFileAttributes);
- m_pkt.setUserId(this.getUserId());
- m_pkt.setTreeId(this.getTreeId());
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- // Set the call parameters
- m_pkt.setParameterCount(8);
- m_pkt.setParameter(0, attrib);
- m_pkt.setParameter(1, 0);
- m_pkt.setParameter(2, 0);
- for (int i = 3; i < 8; i++)
- m_pkt.setParameter(i, 0);
- // Build the full path string
- String fileName = fname;
- if ( fname.startsWith("\\") == false)
- fileName = PCShare.makePath(getWorkingDirectory(), fname);
- // Pack the file name
- m_pkt.resetBytePointer();
- m_pkt.packByte(DataType.ASCII);
- m_pkt.packString(fileName, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the SMB set file information packet
- m_pkt.ExchangeSMB(this, m_pkt, true);
- }
- /**
- * Start a search of the specified directory returning information for each file/directory
- * found.
- *
- * @param dir Directory to start searching. If the directory string does not start with a '\'
- * then the directory name is prepended with the current working directory.
- * @param attr Search attributes, to determine the types of files/directories returned. @see
- * org.alfresco.jlan.server.filesys.FileAttribute
- * @param level Information level required
- * @return SMBSearchContext for this search, else null
- * @exception java.io.IOException If an I/O error occurs
- * @exception SMBException If an SMB level error occurs
- */
- public final SearchContext StartSearch(String dir, int attr, int level)
- throws java.io.IOException, SMBException {
- // Create a new SMB search context
- TransSearchContext srch = new TransSearchContext(this);
- if ( srch == null)
- return null;
- // Start the search and return the search context
- srch.StartSearch(dir, attr, level);
- return srch;
- }
- /**
- * Perform an NTCreateAndX SMB to create/open a file or directory
- *
- * @param name File/directory name
- * @param access Desired access mode.
- * @see org.alfresco.jlan.server.filesys.AccessMode
- * @param attrib Required file attributes.
- * @see org.alfresco.jlan.server.filesys.FileAttribute
- * @param sharing Shared access mode
- * @param exists Action to take if file/directory exists.
- * @see org.alfresco.jlan.server.filesys.FileAction
- * @param initSize Initial file allocation size, in bytes
- * @param createOpt Create file options
- * @return CIFSFile
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final CIFSFile NTCreate(String name, int access, int attrib, int sharing, int exists, long initSize, int createOpt)
- throws IOException, SMBException {
- // Call the main NTCreate method
- return NTCreateInternal(name, 0, access, attrib, sharing, exists, initSize, createOpt, true);
- }
- /**
- * Perform an NTCreateAndX SMB to create/open a file with an oplock
- *
- * @param name File/directory name
- * @param oplockFlags int
- * @param access Desired access mode.
- * @see org.alfresco.jlan.server.filesys.AccessMode
- * @param attrib Required file attributes.
- * @see org.alfresco.jlan.server.filesys.FileAttribute
- * @param sharing Shared access mode
- * @param exists Action to take if file/directory exists.
- * @see org.alfresco.jlan.server.filesys.FileAction
- * @param initSize Initial file allocation size, in bytes
- * @param createOpt Create file options
- * @return CIFSFile
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final CIFSFile NTCreateWithOplock(String name, int oplockFlags, OplockInterface oplockIface,
- int access, int attrib, int sharing, int exists, long initSize, int createOpt)
- throws IOException, SMBException {
- // Call the main NTCreate method
- CIFSFile cifsFile = NTCreateInternal(name, oplockFlags, access, attrib, sharing, exists, initSize, createOpt, true);
- if ( cifsFile != null && cifsFile.getOplockType() != OpLock.TypeNone) {
-
- // Set the oplock interface
-
- cifsFile.setOplockInterface( oplockIface);
-
- // Add the file to the list of oplocked files, need to access the file to call
- // the oplock interface if an oplock break is received asynchronously from the server
-
- if ( m_oplockFiles == null)
- m_oplockFiles = new HashMap<Integer, CIFSFile>();
- m_oplockFiles.put( new Integer( cifsFile.getFileId()), cifsFile);
- }
-
- // Return the file
-
- return cifsFile;
- }
- /**
- * Perform an NT query security descriptor transaction for the specified file or directory
- *
- * @param fid File identifier, via SMBFile.getFileId() of an open file.
- * @param flags Security descriptor elements to return (Owner, Group, SACL, DACL).
- * @see org.alfresco.jlan.smb.nt.SecurityDescriptor
- * @return SecurityDescriptor
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final SecurityDescriptor NTQuerySecurityDescriptor(int fid, int flags)
- throws IOException, SMBException {
- // Check if we have negotiated NT dialect
- if ( getDialect() != Dialect.NT)
- throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.NTTransQuerySecurityDesc, null, 0, 8, 0);
- // Pack the parameter block for the request
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(fid);
- paramBuf.putShort(0);
- paramBuf.putInt(flags);
- // Perform the query security descriptor transaction
- NTTransPacket ntPkt = new NTTransPacket();
- TransactBuffer respBuf = ntPkt.doTransaction(this, reqBuf);
- // Check if a security descriptor has been returned
- SecurityDescriptor secDesc = null;
- if ( respBuf != null && respBuf.hasDataBuffer()) {
- // Get the returned data
- DataBuffer dataBuf = respBuf.getDataBuffer();
- try {
- secDesc = new SecurityDescriptor();
- secDesc.loadDescriptor(dataBuf.getBuffer(), dataBuf.getOffset());
- }
- catch (LoadException ex) {
- secDesc = null;
- }
- }
- // Return the security descriptor
- return secDesc;
- }
- /**
- * Set the security descriptor for the specified file/directory
- *
- * @param fid File identifier, via SMBFile.getFileId() of an open file.
- * @param secdesc Security descriptor
- * @param flags Fields to set (Owner, Group, SACL, DACL).
- * @see org.alfresco.jlan.smb.nt.SecurityDescriptor
- * @exception IOException If a network error occurs
- * @exception SMBException If an SMB level error occurs
- * @exception SaveException If the security descriptor cannot be stored
- */
- public final void NTSetSecurityDescriptor(int fid, SecurityDescriptor secdesc, int flags)
- throws IOException, SMBException, SaveException {
- // Check if we have negotiated NT dialect
- if ( getDialect() != Dialect.NT)
- throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.NTTransSetSecurityDesc, null, 0, 8, 65000);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(fid);
- paramBuf.putShort(0);
- paramBuf.putInt(flags);
- // Pack the data block
- DataBuffer dataBuf = reqBuf.getDataBuffer();
- int len = secdesc.saveDescriptor(dataBuf.getBuffer(), 0);
- dataBuf.setLength(len);
- // Perform the set security descriptor transaction
- NTTransPacket ntPkt = new NTTransPacket();
- ntPkt.doTransaction(this, reqBuf);
- }
- /**
- * Add a change notification filter for the specified directory
- *
- * @param fid File id, from SMBFile.getFileId() of an open directory. The directory should be
- * opened using the NTCreate() method.
- * @param filter Directory watch filter flags. @see org.alfresco.jlan.client.nt.NotifyChange.
- * @param watchTree true to watch sub-directories, false to watch the specified directory only
- * @param handler DirectoryWatcher implementation. @see
- * org.alfresco.jlan.client.smb.DirectoryWatcher
- * @param autoResub true to automatically resubmit the notification filter after an event is
- * received
- * @return AsynchRequest
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final AsynchRequest NTNotifyChange(int fid, int filter, boolean watchTree, DirectoryWatcher handler, boolean autoResub)
- throws IOException, SMBException {
- // Create an asynchronous request to hold the notify details
- NotifyChangeAsynchRequest areq = new NotifyChangeAsynchRequest(-1, fid, filter, watchTree, handler);
- areq.setAutoReset(autoResub);
- // Call the main notify change method to set the notify request
- return NTNotifyChange(areq);
- }
- /**
- * Add a change notification filter for the specified directory
- *
- * @param areq AsynchRequest
- * @return AsynchRequest
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final AsynchRequest NTNotifyChange(AsynchRequest areq)
- throws IOException, SMBException {
- // Check if we have negotiated NT dialect
- if ( getDialect() != Dialect.NT)
- throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
- // Make sure the request is a notify change request
- if ( areq instanceof NotifyChangeAsynchRequest == false)
- throw new IOException("Invalid asynchronous request class, " + areq.getClass().getName());
- // Get the notify change asynchronous request
- NotifyChangeAsynchRequest nreq = (NotifyChangeAsynchRequest) areq;
- // Build the NT notify change transaction SMB packet
- NTTransPacket tpkt = new NTTransPacket();
- tpkt.setUserId(getUserId());
- tpkt.setTreeId(getTreeId());
- tpkt.setFlags(getDefaultFlags());
- tpkt.setFlags2(getDefaultFlags2());
- // Set the multiplex id to identify this notify request
- int mid = getNextMultiplexId();
- tpkt.setMultiplexId(mid);
- // Save the request id and clear the completed status of the request
- nreq.setId(mid);
- nreq.setCompleted(false);
- // Initialize the NT transaction packet
- tpkt.InitializeNTTransact(PacketType.NTTransNotifyChange, null, 0, null, 0, 4, 32, 0);
- tpkt.resetSetupPointer();
- tpkt.packInt(nreq.getFilter());
- tpkt.packWord(nreq.getFileId());
- tpkt.packByte(nreq.hasWatchTree() ? 1 : 0);
- tpkt.packByte(0);
- tpkt.setByteCount(0);
- // Send the notify change transaction
- //
- // Note: There is no response until the notification triggers
- tpkt.SendSMB(this);
- // Add the request to the pending list and return the request
- addAsynchronousRequest(nreq);
- return nreq;
- }
- /**
- * Cancel an outstanding request. Used to cancel change notifications.
- *
- * @param req AsynchRequest
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final void NTCancel(AsynchRequest areq)
- throws IOException, SMBException {
- // Check if we have negotiated NT dialect
- if ( getDialect() != Dialect.NT)
- throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
- // Check if the request has auto-resubmit enabled, if so then disable the resubmit
- if ( areq.hasAutoReset())
- areq.setAutoReset(false);
- // Check if the request has already completed, if so then there is no need to cancel it
- if ( areq.hasCompleted())
- return;
- // Check if there is any data available for this network session, the request we are about
- // to
- // cancel may have just completed
- if ( getSession().hasData()) {
- // Clear out the recieve buffer
- pingServer();
- // Check if the request has now completed
- if ( areq.hasCompleted())
- return;
- }
- // Build the NTCancel SMB packet
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setCommand(PacketType.NTCancel);
- m_pkt.setUserId(getUserId());
- m_pkt.setTreeId(getTreeId());
- m_pkt.setMultiplexId(areq.getId());
- m_pkt.setParameterCount(0);
- m_pkt.setByteCount(0);
- // Send/receive the NT cancel request
- m_pkt.ExchangeSMB(this, m_pkt, false);
- // Check the return status
- boolean isValid = m_pkt.isValidResponse();
- if ( isValid == true)
- return;
- else if ( m_pkt.isLongErrorCode() && m_pkt.getLongErrorCode() == SMBStatus.NTCancelled)
- return;
- else {
- // Throw the SMB exception
- if ( m_pkt.hasLongErrorCode())
- throw new SMBException(SMBStatus.NTErr, m_pkt.getLongErrorCode());
- else
- throw new SMBException(m_pkt.getErrorClass(), m_pkt.getErrorCode());
- }
- }
- /**
- * NT I/O control
- *
- * @param ctrlCode int
- * @param fid int
- * @param fsctl boolean
- * @param data byte[]
- * @param dlen int
- * @param filter int
- * @return DataBuffer
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final DataBuffer NTIOCtl(int ctrlCode, int fid, boolean fsctl, byte[] data, int dlen, int filter)
- throws IOException, SMBException {
- // Check if we have negotiated NT dialect
- if ( getDialect() != Dialect.NT)
- throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.NTTransIOCtl, 8, 0, data, 0, dlen);
- // Pack the setup block
- DataBuffer setupBuf = reqBuf.getSetupBuffer();
- setupBuf.putInt(ctrlCode);
- setupBuf.putShort(fid);
- setupBuf.putByte(fsctl ? 1 : 0);
- setupBuf.putByte(filter);
- // Perform the I/O control transaction
- NTTransPacket ntPkt = new NTTransPacket();
- TransactBuffer respBuf = ntPkt.doTransaction(this, reqBuf);
- // Check if there is any return data
- if ( respBuf != null)
- return respBuf.getDataBuffer();
- return null;
- }
- /**
- * Get file information for the specified open file/directory, returning the requested
- * information level
- *
- * @param fid File id for the file or directory, from SMBFile.getFileId().
- * @param level Information level. @see org.alfresco.jlan.smb.FileInfoLevel
- * @return FileInfo
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final FileInfo NTGetFileInformation(int fid, int level)
- throws IOException, SMBException {
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFile, null, 0, 4, 0);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(fid);
- paramBuf.putShort(level);
- // Perform the get file information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
- // Unpack the received file information data
- FileInfo finfo = null;
- if ( respBuf != null && respBuf.hasDataBuffer()) {
- // Unpack the file information
- DataBuffer buf = respBuf.getDataBuffer();
- switch (level) {
- case FileInfoLevel.PathStandard:
- finfo = FileInfoPacker.unpackFileInfoStandard("", buf, false);
- break;
- case FileInfoLevel.PathQueryEASize:
- finfo = FileInfoPacker.unpackFileInfoStandard("", buf, true);
- break;
- case FileInfoLevel.PathAllEAs:
- break;
- case FileInfoLevel.PathFileBasicInfo:
- finfo = FileInfoPacker.unpackQueryBasicInfo("", buf);
- break;
- case FileInfoLevel.PathFileStandardInfo:
- finfo = FileInfoPacker.unpackQueryStandardInfo("", buf);
- break;
- case FileInfoLevel.PathFileEAInfo:
- finfo = FileInfoPacker.unpackQueryEAInfo("", buf);
- break;
- case FileInfoLevel.PathFileNameInfo:
- finfo = FileInfoPacker.unpackQueryNameInfo(buf, respBuf.isUnicode());
- break;
- case FileInfoLevel.PathFileAllInfo:
- finfo = FileInfoPacker.unpackQueryAllInfo(buf, respBuf.isUnicode());
- break;
- case FileInfoLevel.PathFileAltNameInfo:
- finfo = FileInfoPacker.unpackQueryNameInfo(buf, respBuf.isUnicode());
- break;
- case FileInfoLevel.PathFileStreamInfo:
- finfo = FileInfoPacker.unpackQueryStreamInfo("", buf, respBuf.isUnicode());
- break;
- case FileInfoLevel.PathFileCompressionInfo:
- finfo = FileInfoPacker.unpackQueryCompressionInfo("", buf);
- break;
- }
- }
- // If the file information is valid, set the file id so the file information can be used
- // to set information
- if ( finfo != null)
- finfo.setFileId(fid);
- // Return the file information
- return finfo;
- }
- /**
- * Get file information for the specified open file/directory, returning the requested
- * information level
- *
- * @param fid File id for the file or directory, from SMBFile.getFileId().
- * @param level Information level. @see org.alfresco.jlan.smb.FileInfoLevel
- * @return TransactBuffer
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final TransactBuffer NTGetFileInformationRaw(int fid, int level)
- throws IOException, SMBException {
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFile, null, 0, 4, 0);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(fid);
- paramBuf.putShort(level);
- // Perform the get file information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- return tpkt.doTransaction(this, reqBuf);
- }
- /**
- * Set file information that allows setting different information levels
- *
- * @param finfo FileInfo
- * @param level Information level. @see org.alfresco.jlan.smb.FileInfoLevel
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final void NTSetFileInformation(FileInfo finfo, int level)
- throws IOException, SMBException {
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2SetFile, null, 0, 6, 65000);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(finfo.getFileId());
- paramBuf.putShort(level);
- paramBuf.putShort(0);
- // Pack the file information into the data buffer
- DataBuffer dataBuf = reqBuf.getDataBuffer();
- switch (level) {
- case FileInfoLevel.SetStandard:
- FileInfoPacker.packFileInfoStandard(finfo, dataBuf, false);
- break;
- case FileInfoLevel.SetQueryEASize:
- FileInfoPacker.packFileInfoStandard(finfo, dataBuf, true);
- break;
- case FileInfoLevel.SetBasicInfo:
- FileInfoPacker.packFileBasicInfo(finfo, dataBuf);
- break;
- case FileInfoLevel.SetDispositionInfo:
- break;
- case FileInfoLevel.SetAllocationInfo:
- break;
- case FileInfoLevel.SetEndOfFileInfo:
- break;
- }
- ;
- // Perform the get file information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- tpkt.doTransaction(this, reqBuf);
- }
- /**
- * Set the delete on close flag for an open file
- *
- * @param fid File id for the file or directory, from SMBFile.getFileId().
- * @param delFlag true to delete the file on close, or false to clear a previous delete on close
- * request
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final void NTSetDeleteOnClose(int fid, boolean delFlag)
- throws IOException, SMBException {
- // Create the data block for the set file disposition info level (0x102)
- byte[] dblock = new byte[4];
- dblock[0] = delFlag == true ? (byte) 1 : (byte) 0;
- // Set the delete on close setting for the open file
- NTSetFileInformationRaw(fid, dblock, 2, 0x102);
- }
- /**
- * Set the end of file position for the open file
- *
- * @param fid File id for the file or directory, from SMBFile.getFileId().
- * @param pos New end of file position
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final void NTSetEndOfFile(int fid, long pos)
- throws IOException, SMBException {
- // Create the data block for the set end of file info level (0x104)
- byte[] dblock = new byte[8];
- DataPacker.putIntelLong(pos, dblock, 0);
- // Set the end of file position for the open file
- NTSetFileInformationRaw(fid, dblock, 8, 0x104);
- }
- /**
- * Set the file allocation size for the open file
- *
- * @param fid File id for the file or directory, from SMBFile.getFileId().
- * @param alloc New file allocation size
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- public final void NTSetFileAllocation(int fid, long alloc)
- throws IOException, SMBException {
- // Create the data block for the set file allocation info level (0x103)
- byte[] dblock = new byte[8];
- DataPacker.putIntelLong(alloc, dblock, 0);
- // Set the file allocation for the open file
- NTSetFileInformationRaw(fid, dblock, 8, 0x103);
- }
- /**
- * Set file information that allows setting different information levels
- *
- * @param fid File id for the file or directory, from SMBFile.getFileId().
- * @param data Raw file information data block.
- * @param dlen Raw data block length.
- * @param level File information level. @see org.alfresco.jlan.smb.FileInfoLevel
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- private final void NTSetFileInformationRaw(int fid, byte[] data, int dlen, int level)
- throws IOException, SMBException {
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2SetFile, 0, 6, data, 0, dlen);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(fid);
- paramBuf.putShort(level);
- paramBuf.putShort(0);
- // Perform the get file information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- tpkt.doTransaction(this, reqBuf);
- }
- /**
- * Get the device information
- *
- * @return DeviceInfo @see org.alfresco.jlan.client.info.DeviceInfo
- * @exception IOException
- * @exception SMBException
- */
- public final DeviceInfo NTGetDeviceInfo()
- throws IOException, SMBException {
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFileSys, null, 0, 2, 0);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(FileInfoLevel.FSInfoQueryDevice);
- // Perform the get file information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
- // Unpack the received device information data
- DeviceInfo devInfo = null;
- if ( respBuf != null && respBuf.hasDataBuffer()) {
- // Unpack the device information
- DataBuffer buf = respBuf.getDataBuffer();
- int typ = buf.getInt();
- int chr = buf.getInt();
- // Return the device information
- devInfo = new DeviceInfo(typ, chr);
- }
- // Return the device information
- return devInfo;
- }
- /**
- * Get the device attributes information
- *
- * @return DeviceAttributesInfo
- * @exception IOException
- * @exception SMBException
- */
- public final DeviceAttributesInfo NTGetDeviceAttributes()
- throws IOException, SMBException {
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFileSys, null, 0, 2, 0);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(FileInfoLevel.FSInfoQueryAttribute);
- // Perform the get file information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
- // Unpack the received device attribute information data
- DeviceAttributesInfo attrInfo = null;
- if ( respBuf != null && respBuf.hasDataBuffer()) {
- // Unpack the device attribute information
- DataBuffer buf = respBuf.getDataBuffer();
- int attr = buf.getInt();
- int maxLen = buf.getInt();
- int lblLen = buf.getInt();
- if ( respBuf.isUnicode())
- lblLen = lblLen / 2;
- String label = buf.getString(lblLen, respBuf.isUnicode());
- // Return the device attributes
- attrInfo = new DeviceAttributesInfo(attr, maxLen, label);
- }
- // Return the device attribute information
- return attrInfo;
- }
- /**
- * Get file information for the specified file.
- *
- * @param fname File name of the file to return information for.
- * @param level Information level required. @see org.alfresco.jlan.smb.FileInfoLevel
- * @return TransactBuffer
- * @exception java.io.IOException If an I/O error occurs.
- * @exception java.io.FileNotFoundException If the remote file does not exist.
- * @exception SMBException If an SMB level error occurs
- */
- public final TransactBuffer getFileInformationRaw(String fname, int level)
- throws java.io.IOException, java.io.FileNotFoundException, SMBException {
- // Build the file name/path string
- String pathName = fname;
- if ( pathName.startsWith("\\") == false)
- pathName = PCShare.makePath(getWorkingDirectory(), fname);
- // Create the request transaction buffer
- TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryPath, null, 0, 512, 0);
- // Pack the parameter block
- DataBuffer paramBuf = reqBuf.getParameterBuffer();
- paramBuf.putShort(level);
- paramBuf.putInt(0);
- paramBuf.putString(pathName, isUnicode());
- // Perform the get file information transaction
- TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
- return tpkt.doTransaction(this, reqBuf);
- }
- /**
- * Return the details for a symlink file/folder
- *
- * @param linkPath String
- * @return SymLink
- * @exception Exception
- */
- public final SymLink getSymLinkDetails(String linkPath)
- throws Exception {
- // Open the symlink file
- CIFSFile linkFile = NTCreateInternal(linkPath, 0, AccessMode.NTRead + AccessMode.NTReadControl + AccessMode.NTReadAttrib
- + AccessMode.NTReadEA, FileAttribute.NTNormal, SharingMode.READWRITE, FileAction.NTOpen, 0,
- WinNT.CreateReparsePoint, false);
- SymLink symLink = null;
- Exception retError = null;
- try {
- // Make sure the file is a reparse point
- if ( linkFile.isReparsePoint()) {
- // Get the symlink details
- int ioctlCode = NTIOCtl.makeControlCode(NTIOCtl.DeviceFileSystem, NTIOCtl.FsCtlGetReparsePoint,
- NTIOCtl.MethodBuffered, NTIOCtl.AccessAny);
- DataBuffer linkBuf = NTIOCtl(ioctlCode, linkFile.getFileId(), true, null, 0, 0);
- // Parse the returned structure
- symLink = new SymLink(linkBuf);
- }
- else {
- // Return an exception
- retError = new IOException("Not a reparse point, " + linkPath);
- }
- }
- catch (Exception ex) {
- // Save the error
- retError = ex;
- }
- finally {
- // Close the link file
- try {
- linkFile.Close();
- }
- catch (Exception ex) {
- }
- }
- // Check if there is an error to return
- if ( retError != null)
- throw retError;
- // Return the symlink details
- return symLink;
- }
- /**
- * Process incoming data checking for asynchronous response packets from the server
- *
- * @param waitTime Receive timeout in milliseconds, zero for no timeout or -1 to not wait for
- * data
- * @exception IOException
- * @exception SMBException
- */
- public final void checkForAsynchReceive(int waitTime)
- throws IOException, SMBException {
- // Check if there is any data in the socket receive buffer, if the caller does not want
- // to wait for a packet then return immediately
- if ( waitTime == -1 && getSession().hasData() == false) {
- // Check if we need to send an echo packet to the server to keep the SMB session alive
- if ( (m_pkt.getLastPacketSendTime() + SessionKeepAlive) < System.currentTimeMillis())
- pingServer();
- return;
- }
- // Wait for an asynchronous response from the server
- m_pkt.ReceiveAsynchSMB(this, waitTime == -1 ? 0 : waitTime);
- // Check if we need to send an echo packet to the server to keep the SMB session alive.
- //
- // The asynchronous receive will usually result in the request being reset on the server, if
- // not then we may need to send an echo request.
- if ( (m_pkt.getLastPacketSendTime() + SessionKeepAlive) < System.currentTimeMillis())
- pingServer();
- }
-
- /**
- * Refresh the file information for an open file
- *
- * @param smbFile SMBFile
- */
- public void refreshFileInformation( SMBFile smbFile)
- throws IOException, SMBException {
-
- }
-
- /**
- * Process an asynchronous response packet
- *
- * @param pkt SMBPacket
- */
- protected void processAsynchResponse(SMBPacket pkt) {
- // Check for a locking request from the server, an oplock break
-
- if ( pkt.isRequest() == true && pkt.getCommand() == PacketType.LockingAndX) {
-
- // Unpack the file id and flags
-
- int fileId = pkt.getParameter( 2);
- int flags = pkt.getParameter( 3);
-
- // Check for an oplock break
-
- if ( m_oplockFiles != null && ( flags & LockingAndX.OplockBreak) != 0) {
- try {
-
- // Find the oplocked file
-
- CIFSFile cifsFile = m_oplockFiles.get( new Integer( fileId));
- int breakToOpLock = OpLock.TypeNone;
-
- if ( cifsFile != null) {
-
- // Check if the file has an oplock callback interface
-
- if ( cifsFile.getOplockInterface() != null) {
- // Call the oplock interface
-
- breakToOpLock = cifsFile.getOplockInterface().oplockBreak( cifsFile);
- }
- else {
-
- // Flush any pending data on the file
-
- cifsFile.Flush();
- }
- }
-
- // Check if an oplock break response should be sent
-
- if ( cifsFile.getOplockInterface().sendAutomaticBreakResponse() == true) {
- // Build an oplock break response
-
- SMBPacket respPkt = new SMBPacket( 128);
-
- respPkt.setCommand(PacketType.LockingAndX);
- respPkt.setUserId(this.getUserId());
- respPkt.setTreeId(this.getTreeId());
-
- respPkt.setFlags(getDefaultFlags() + SMBPacket.FLG_RESPONSE);
- respPkt.setFlags2(getDefaultFlags2());
-
- respPkt.setParameterCount(8);
- respPkt.setAndXCommand( PacketType.NoChainedCommand);
- respPkt.setParameter(1, 0); // AndX offset
- respPkt.setParameter(2, fileId);
-
- // Break the oplock, or break to a level II shared oplock
-
- if ( breakToOpLock == OpLock.TypeLevelII)
- respPkt.setParameter(3, LockingAndX.OplockBreak + LockingAndX.Level2OpLock);
- else
- respPkt.setParameter(3, LockingAndX.OplockBreak);
-
- respPkt.setParameterLong(4, 0); // timeout
- respPkt.setParameter(6, 0); // number of unlocks
- respPkt.setParameter(7, 0); // number of locks
-
- respPkt.setByteCount( 0);
-
- // Send the oplock break to the server
- //
- // Note: The response flag must be set, and we do not expect a response from the server
-
- respPkt.SendSMB( this);
-
- // Set the new oplock type on the file
-
- cifsFile.setOplockType( breakToOpLock);
- cifsFile.setOplockInterface( null);
- }
- }
- catch (Exception ex) {
-
- }
- }
- }
- else {
-
- // Check if there are any pending asynchronous requests queued
-
- if ( m_asynchRequests == null || m_asynchRequests.size() == 0)
- return;
-
- // Find the matching asynchronous request and remove from the pending list
-
- AsynchRequest areq = removeAsynchronousRequest(pkt.getMultiplexId());
- if ( areq == null)
- return;
-
- // Mark the asynchronous request as completed
-
- areq.setCompleted(true);
-
- // Pass the packet to the asynchronous request for processing
-
- areq.processResponse(this, pkt);
-
- // Check if the request should be automatically resubmitted
-
- if ( areq.hasAutoReset()) {
-
- // Resubmit the request
-
- if ( areq.resubmitRequest(this, null) == true)
- addAsynchronousRequest(areq);
- }
- }
- }
- /**
- * Add an asynchronous request to the list of pending requests
- *
- * @param req AsynchRequest
- */
- protected final void addAsynchronousRequest(AsynchRequest req) {
- // Check if the asynchronous request list has been allocated
- if ( m_asynchRequests == null)
- m_asynchRequests = new ArrayList<AsynchRequest>();
- // Add the request to the list
- m_asynchRequests.add(req);
- }
- /**
- * Remove an asynchronous request from the pending list
- *
- * @param id int
- * @return AsynchRequest
- */
- protected final AsynchRequest removeAsynchronousRequest(int id) {
- // Check if the list is valid
- if ( m_asynchRequests == null)
- return null;
- // Find the request
- AsynchRequest areq = null;
- int idx = 0;
- while (idx < m_asynchRequests.size() && areq == null) {
- // Get the current request and check if it is the required request
- AsynchRequest curReq = m_asynchRequests.get(idx);
- if ( curReq.getId() == id)
- areq = curReq;
- else
- idx++;
- }
- // Remove the request from the list
- if ( areq != null)
- m_asynchRequests.remove(areq);
- // Return the removed request
- return areq;
- }
- /**
- * Remove an asynchronous request from the pending list
- *
- * @param req AsynchRequest
- * @return AsynchRequest
- */
- protected final AsynchRequest removeAsynchronousRequest(AsynchRequest req) {
- // Check if the list is valid
- if ( m_asynchRequests == null)
- return null;
- // Remove the request from the list
- m_asynchRequests.remove(req);
- return req;
- }
- /**
- * Perform an NTCreateAndX SMB to create/open a file or directory
- *
- * @param name File/directory name
- * @param createFlags int
- * @param access Desired access mode.
- * @see org.alfresco.jlan.server.filesys.AccessMode
- * @param attrib Required file attributes.
- * @see org.alfresco.jlan.server.filesys.FileAttribute
- * @param sharing Shared access mode
- * @param exists Action to take if file/directory exists.
- * @see org.alfresco.jlan.server.filesys.FileAction
- * @param initSize Initial file allocation size, in bytes
- * @param createOpt Create file options
- * @param throwErr Throw errors from the CIFS packet exchange
- * @return CIFSFile
- * @exception IOException
- * @exception SMBException If an SMB level error occurs
- */
- protected final CIFSFile NTCreateInternal(String name, int createFlags, int access, int attrib, int sharing, int exists, long initSize,
- int createOpt, boolean throwErr)
- throws IOException, SMBException {
- // Check if we have negotiated NT dialect
- if ( getDialect() != Dialect.NT)
- throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
- // Build the NTCreateAndX SMB packet
- m_pkt.setFlags(getDefaultFlags());
- m_pkt.setFlags2(getDefaultFlags2());
- m_pkt.setCommand(PacketType.NTCreateAndX);
- m_pkt.setUserId(getUserId());
- m_pkt.setTreeId(getTreeId());
- m_pkt.setParameterCount(24);
- m_pkt.resetParameterPointer();
- m_pkt.packByte(0xFF); // no chained command
- m_pkt.packByte(0); // reserved
- m_pkt.packWord(0); // AndX offset
- m_pkt.packByte(0); // reserved
- m_pkt.packWord((name.length() * 2) + 2); // name length in bytes, inc null
- m_pkt.packInt(createFlags); // oplocks/extended response
- m_pkt.packInt(0); // root FID
- m_pkt.packInt(access); // desired access mode
- m_pkt.packLong(initSize); // allocation size
- m_pkt.packInt(attrib); // file attributes
- m_pkt.packInt(sharing); // share access mode
- m_pkt.packInt(exists); // action to take if file exists
- m_pkt.packInt(createOpt); // file create options
- m_pkt.packInt(2); // impersonation level, 0=anonymous, 2=impersonation
- m_pkt.packByte(0); // security flags
- m_pkt.resetBytePointer();
- m_pkt.packString(name, m_pkt.isUnicode());
- m_pkt.setByteCount();
- // Send/receive the NT create andX request
- m_pkt.ExchangeSMB(this, m_pkt, throwErr);
- // Unpack the file/directory details
- m_pkt.resetParameterPointer();
- m_pkt.skipBytes(4);
- int oplockTyp = m_pkt.unpackByte();
- int fid = m_pkt.unpackWord();
- int createAction = m_pkt.unpackInt();
- long createTime = m_pkt.unpackLong();
- long lastAccessTime = m_pkt.unpackLong();
- long lastWriteTime = m_pkt.unpackLong();
- long changeTime = m_pkt.unpackLong();
- int attr = m_pkt.unpackInt();
- long allocSize = m_pkt.unpackLong();
- long eofOffset = m_pkt.unpackLong();
- int devType = m_pkt.unpackWord();
- // Create the file information
- FileInfo finfo = new FileInfo(name, eofOffset, attr);
- finfo.setFileId(fid);
- // Convert the granted oplock type to internal type
-
- if ( oplockTyp == WinNT.GrantedOplockBatch)
- oplockTyp = OpLock.TypeBatch;
- else if ( oplockTyp == WinNT.GrantedOplockExclusive)
- oplockTyp = OpLock.TypeExclusive;
- else if ( oplockTyp == WinNT.GrantedOplockLevelII)
- oplockTyp = OpLock.TypeLevelII;
- else
- oplockTyp = OpLock.TypeNone;
-
- // Create the file object
- return new CIFSFile(this, finfo, fid, oplockTyp);
- }
-
- /**
- * File closed, remove from the oplocked file list
- *
- * @param cifsFile CIFSFile
- */
- protected final void fileClosed( CIFSFile cifsFile) {
-
- // Check if there are any oplocked files
-
- if ( m_oplockFiles == null || m_oplockFiles.size() == 0)
- return;
-
- // Remove the file from the oplocked list
-
- m_oplockFiles.remove( new Integer( cifsFile.getFileId()));
- }
- }
|