CIFSDiskSession.java 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237
  1. /*
  2. * Copyright (C) 2006-2010 Alfresco Software Limited.
  3. *
  4. * This file is part of Alfresco
  5. *
  6. * Alfresco is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Alfresco is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package org.alfresco.jlan.client;
  20. import java.io.*;
  21. import java.util.*;
  22. import org.alfresco.jlan.client.info.DeviceAttributesInfo;
  23. import org.alfresco.jlan.client.info.DeviceInfo;
  24. import org.alfresco.jlan.client.info.DiskInfo;
  25. import org.alfresco.jlan.client.info.FileInfo;
  26. import org.alfresco.jlan.client.info.VolumeInfo;
  27. import org.alfresco.jlan.client.smb.DirectoryWatcher;
  28. import org.alfresco.jlan.server.filesys.AccessMode;
  29. import org.alfresco.jlan.server.filesys.FileAction;
  30. import org.alfresco.jlan.server.filesys.FileAttribute;
  31. import org.alfresco.jlan.smb.DataType;
  32. import org.alfresco.jlan.smb.Dialect;
  33. import org.alfresco.jlan.smb.FileInfoLevel;
  34. import org.alfresco.jlan.smb.LockingAndX;
  35. import org.alfresco.jlan.smb.NTTime;
  36. import org.alfresco.jlan.smb.OpLock;
  37. import org.alfresco.jlan.smb.PCShare;
  38. import org.alfresco.jlan.smb.PacketType;
  39. import org.alfresco.jlan.smb.SMBException;
  40. import org.alfresco.jlan.smb.SMBStatus;
  41. import org.alfresco.jlan.smb.SharingMode;
  42. import org.alfresco.jlan.smb.TransactBuffer;
  43. import org.alfresco.jlan.smb.WinNT;
  44. import org.alfresco.jlan.smb.nt.LoadException;
  45. import org.alfresco.jlan.smb.nt.SaveException;
  46. import org.alfresco.jlan.smb.nt.SecurityDescriptor;
  47. import org.alfresco.jlan.smb.nt.SymLink;
  48. import org.alfresco.jlan.util.DataBuffer;
  49. import org.alfresco.jlan.util.DataPacker;
  50. import org.alfresco.jlan.smb.nt.NTIOCtl;
  51. /**
  52. * SMB CIFS disk session class
  53. *
  54. * <p>
  55. * The CIFSDiskSession class extends the DiskSession class and provides CIFS protocol specific
  56. * implementations for the DiskSession methods.
  57. *
  58. * <p>
  59. * An CIFSDiskSession object will be created by the SessionFactory static class when the negotiated
  60. * SMB dialect indicates that the remote server supports an SMB dialect greater than Core or
  61. * CorePlus.
  62. *
  63. * <p>
  64. * The SessionFactory.OpenDisk() method is used to create a session to a remote disk share. A
  65. * PCShare object specifies the remote server and share to connect to, along with any required
  66. * access control.
  67. *
  68. * @author gkspencer
  69. */
  70. public final class CIFSDiskSession extends DiskSession {
  71. // Constants
  72. //
  73. // SMB session keep-alive interval
  74. private final static long SessionKeepAlive = 60000L;
  75. // List of pending asynchronous requests
  76. private List<AsynchRequest> m_asynchRequests;
  77. // List of open files with an oplock
  78. private HashMap<Integer, CIFSFile> m_oplockFiles;
  79. /**
  80. * Class constructor
  81. *
  82. * @param shr Remote server details.
  83. * @param dialect SMB dialect that this session is using
  84. */
  85. protected CIFSDiskSession(PCShare shr, int dialect) {
  86. super(shr, dialect);
  87. }
  88. /**
  89. * Close this connection with the remote server share.
  90. *
  91. * @exception java.io.IOException If an I/O error occurs.
  92. * @exception SMBException If an SMB level error occurs
  93. */
  94. public void CloseSession()
  95. throws java.io.IOException, SMBException {
  96. // Build a tree disconnect packet
  97. m_pkt.setCommand(PacketType.TreeDisconnect);
  98. m_pkt.setUserId(getUserId());
  99. m_pkt.setTreeId(m_treeid);
  100. m_pkt.setParameterCount(0);
  101. m_pkt.setByteCount(0);
  102. // Send the tree disconnect packet
  103. m_pkt.ExchangeSMB(this, m_pkt);
  104. // Indicate that the session has been closed
  105. m_treeid = DiskSession.Closed;
  106. // Close the network session
  107. super.CloseSession();
  108. }
  109. /**
  110. * Create a new directory on the remote file server.
  111. *
  112. * @param dir Directory name string. If the directory name does not have a leading '\' the
  113. * current working directory for this session will be prepended to the string.
  114. * @exception java.io.IOException If an I/O error occurs.
  115. * @exception SMBException If an SMB level error occurs
  116. */
  117. public final void CreateDirectory(String dir)
  118. throws java.io.IOException, SMBException {
  119. // Build the new path
  120. String newPath = dir;
  121. if ( newPath.startsWith("\\") == false)
  122. newPath = PCShare.makePath(getWorkingDirectory(), dir);
  123. // Pre-NT dialect create directory
  124. if ( getDialect() != Dialect.NT || isUnicode() == false) {
  125. // Create an SMB create directory packet
  126. m_pkt.setCommand(PacketType.CreateDirectory);
  127. m_pkt.setUserId(this.getUserId());
  128. m_pkt.setTreeId(this.getTreeId());
  129. m_pkt.setFlags(getDefaultFlags());
  130. m_pkt.setFlags2(getDefaultFlags2());
  131. m_pkt.setParameterCount(0);
  132. // Copy the directory name data block to the SMB packet
  133. m_pkt.resetBytePointer();
  134. m_pkt.packByte(DataType.ASCII);
  135. m_pkt.packString(newPath, m_pkt.isUnicode());
  136. m_pkt.setByteCount();
  137. // Send/receive the SMB create directory packet
  138. m_pkt.ExchangeSMB(this, m_pkt, true);
  139. }
  140. else {
  141. // Use the NTCreateAndX SMB to create the directory
  142. CIFSFile dirFile = NTCreate(newPath, AccessMode.NTRead, FileAttribute.NTDirectory, SharingMode.READWRITE,
  143. FileAction.NTCreate, 0, WinNT.CreateDirectory);
  144. // Close the directory file
  145. dirFile.Close();
  146. }
  147. }
  148. /**
  149. * Create and open a file on the remote file server.
  150. *
  151. * @param fname Remote file name string.
  152. * @return SMBFile for the opened file, else null.
  153. * @exception java.io.IOException If an I/O error occurs
  154. * @exception SMBException If an SMB error occurs
  155. */
  156. public final SMBFile CreateFile(String fname)
  157. throws java.io.IOException, SMBException {
  158. // Create a new file
  159. return OpenFile(fname, AccessMode.WriteOnly);
  160. }
  161. /**
  162. * Delete the specified directory on the remote file server.
  163. *
  164. * @param dir Directory name string. If the directory name does not have a leading '\' the
  165. * current working directory for this session will be preprended to the string.
  166. * @exception java.io.IOException If an I/O error occurs.
  167. * @exception SMBException If an SMB level error occurs
  168. */
  169. public final void DeleteDirectory(String dir)
  170. throws java.io.IOException, SMBException {
  171. // Create an SMB delete directory packet
  172. m_pkt.setFlags(getDefaultFlags());
  173. m_pkt.setFlags2(getDefaultFlags2());
  174. m_pkt.setCommand(PacketType.DeleteDirectory);
  175. m_pkt.setUserId(this.getUserId());
  176. m_pkt.setTreeId(this.getTreeId());
  177. m_pkt.setParameterCount(0);
  178. // Check if the directory name contains a path
  179. String delPath = dir;
  180. if ( delPath.startsWith("\\") == false)
  181. delPath = PCShare.makePath(getWorkingDirectory(), dir);
  182. // Pack the path to be deleted
  183. m_pkt.resetBytePointer();
  184. m_pkt.packByte(DataType.ASCII);
  185. m_pkt.packString(delPath, m_pkt.isUnicode());
  186. m_pkt.setByteCount();
  187. // Send/receive the SMB delete directory packet
  188. m_pkt.ExchangeSMB(this, m_pkt, true);
  189. }
  190. /**
  191. * Delete the specified file on the remote file server.
  192. *
  193. * @param fname File name of the remote file to delete. If the file name does not have a leading
  194. * '\' the current working directory for this session will be prepended to the
  195. * string.
  196. * @param attr File attributes of the file(s) to delete.
  197. * @exception java.io.IOException If an I/O error occurs.
  198. * @exception SMBException If an SMB level error occurs
  199. */
  200. public final void DeleteFile(String fname, int attr)
  201. throws java.io.IOException, SMBException {
  202. // Create an SMB delete file packet
  203. m_pkt.setFlags(getDefaultFlags());
  204. m_pkt.setFlags2(getDefaultFlags2());
  205. m_pkt.setCommand(PacketType.DeleteFile);
  206. m_pkt.setUserId(this.getUserId());
  207. m_pkt.setTreeId(this.getTreeId());
  208. m_pkt.setParameterCount(1);
  209. m_pkt.setParameter(0, attr);
  210. // Check if the file name contains a path
  211. String delName = fname;
  212. if ( delName.startsWith("\\") == false)
  213. delName = PCShare.makePath(getWorkingDirectory(), fname);
  214. // Copy the file name data block to the SMB packet
  215. m_pkt.resetBytePointer();
  216. m_pkt.packByte(DataType.ASCII);
  217. m_pkt.packString(delName, m_pkt.isUnicode());
  218. m_pkt.setByteCount();
  219. // Send/receive the SMB delete file packet
  220. m_pkt.ExchangeSMB(this, m_pkt, true);
  221. }
  222. /**
  223. * Get disk information for this remote disk.
  224. *
  225. * @return Disk information object, or null.
  226. * @exception java.io.IOException If an I/O error occurs.
  227. * @exception SMBException If an SMB level error occurs
  228. */
  229. public final DiskInfo getDiskInformation()
  230. throws java.io.IOException, SMBException {
  231. // Check if the NT dialect has been negotiated, or LanMan
  232. if ( this.getDialect() != Dialect.NT) {
  233. // Create a query disk information SMB packet
  234. m_pkt.setFlags(getDefaultFlags());
  235. m_pkt.setFlags2(getDefaultFlags2());
  236. m_pkt.setCommand(PacketType.DiskInformation);
  237. m_pkt.setUserId(this.getUserId());
  238. m_pkt.setTreeId(this.getTreeId());
  239. m_pkt.setParameterCount(0);
  240. m_pkt.setByteCount(0);
  241. // Send/receive the SMB file information packet
  242. m_pkt.ExchangeSMB(this, m_pkt, true);
  243. // Extract the disk information from the received SMB packet
  244. int totunit = m_pkt.getParameter(0);
  245. int blkperunit = m_pkt.getParameter(1);
  246. int blksize = m_pkt.getParameter(2);
  247. int freeblk = m_pkt.getParameter(3);
  248. // Create a disk information object
  249. return new DiskInfo(getPCShare(), totunit, blkperunit, blksize, freeblk);
  250. }
  251. else {
  252. // Create the transaction request
  253. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFileSys, null, 0, 2, 0);
  254. // Pack the parameter block
  255. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  256. paramBuf.putShort(FileInfoLevel.FSInfoQuerySize);
  257. // Perform the get file system information transaction
  258. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  259. TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
  260. // Unpack the response data
  261. DiskInfo dinfo = null;
  262. if ( respBuf != null && respBuf.hasDataBuffer()) {
  263. // Unpack the file system information
  264. DataBuffer dataBuf = respBuf.getDataBuffer();
  265. long fsTotalUnit = dataBuf.getLong();
  266. long fsAvailUnit = dataBuf.getLong();
  267. int fsSectorsPerUnit = dataBuf.getInt();
  268. int fsBytesPerSector = dataBuf.getInt();
  269. // Create the disk information details
  270. dinfo = new DiskInfo(getPCShare(), fsTotalUnit, fsSectorsPerUnit, fsBytesPerSector, fsAvailUnit);
  271. }
  272. // Return the disk information
  273. return dinfo;
  274. }
  275. }
  276. /**
  277. * Get file information for the specified file.
  278. *
  279. * @param fname File name of the file to return information for.
  280. * @see org.alfresco.jlan.smb.FileInfoLevel
  281. * @param level Information level required
  282. * @return FileInfo if the request was successful, else null.
  283. * @exception java.io.IOException If an I/O error occurs.
  284. * @exception java.io.FileNotFoundException If the remote file does not exist.
  285. * @exception SMBException If an SMB level error occurs
  286. */
  287. public final FileInfo getFileInformation(String fname, int level)
  288. throws java.io.IOException, java.io.FileNotFoundException, SMBException {
  289. // Build the file name/path string
  290. String pathName = fname;
  291. if ( pathName.startsWith("\\") == false)
  292. pathName = PCShare.makePath(getWorkingDirectory(), fname);
  293. // Create the request transaction buffer
  294. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryPath, null, 0, 512, 0);
  295. // Pack the parameter block
  296. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  297. paramBuf.putShort(level);
  298. paramBuf.putInt(0);
  299. paramBuf.putString(pathName, isUnicode());
  300. // Perform the get file information transaction
  301. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  302. TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
  303. // Unpack the received file information data
  304. FileInfo finfo = null;
  305. if ( respBuf != null && respBuf.hasDataBuffer()) {
  306. // Unpack the file information
  307. DataBuffer buf = respBuf.getDataBuffer();
  308. switch (level) {
  309. case FileInfoLevel.PathStandard:
  310. finfo = FileInfoPacker.unpackFileInfoStandard("", buf, false);
  311. break;
  312. case FileInfoLevel.PathQueryEASize:
  313. finfo = FileInfoPacker.unpackFileInfoStandard("", buf, true);
  314. break;
  315. case FileInfoLevel.PathAllEAs:
  316. finfo = FileInfoPacker.unpackQueryAllEAs("", buf);
  317. break;
  318. case FileInfoLevel.PathFileBasicInfo:
  319. finfo = FileInfoPacker.unpackQueryBasicInfo("", buf);
  320. break;
  321. case FileInfoLevel.PathFileStandardInfo:
  322. finfo = FileInfoPacker.unpackQueryStandardInfo("", buf);
  323. break;
  324. case FileInfoLevel.PathFileEAInfo:
  325. finfo = FileInfoPacker.unpackQueryEAInfo("", buf);
  326. break;
  327. case FileInfoLevel.PathFileNameInfo:
  328. finfo = FileInfoPacker.unpackQueryNameInfo(buf, respBuf.isUnicode());
  329. break;
  330. case FileInfoLevel.PathFileAllInfo:
  331. finfo = FileInfoPacker.unpackQueryAllInfo(buf, respBuf.isUnicode());
  332. break;
  333. case FileInfoLevel.PathFileAltNameInfo:
  334. finfo = FileInfoPacker.unpackQueryNameInfo(buf, respBuf.isUnicode());
  335. break;
  336. case FileInfoLevel.PathFileStreamInfo:
  337. finfo = FileInfoPacker.unpackQueryStreamInfo("", buf, respBuf.isUnicode());
  338. break;
  339. case FileInfoLevel.PathFileCompressionInfo:
  340. finfo = FileInfoPacker.unpackQueryCompressionInfo("", buf);
  341. break;
  342. }
  343. }
  344. // Return the file information
  345. return finfo;
  346. }
  347. /**
  348. * Get the disk volume information
  349. *
  350. * @return VolumeInfo, or null
  351. * @exception java.io.IOException If an I/O error occurs
  352. * @exception SMBException If an SMB level error occurs
  353. */
  354. public final VolumeInfo getVolumeInformation()
  355. throws java.io.IOException, SMBException {
  356. // Check if the NT dialect has been negotiated, or LanMan
  357. VolumeInfo volInfo = null;
  358. if ( this.getDialect() != Dialect.NT) {
  359. // Build the search request
  360. m_pkt.setCommand(PacketType.Search);
  361. m_pkt.setUserId(getUserId());
  362. m_pkt.setTreeId(getTreeId());
  363. // Initialize the search SMB packet
  364. m_pkt.setFlags(getDefaultFlags());
  365. m_pkt.setFlags2(getDefaultFlags2());
  366. m_pkt.setParameterCount(2);
  367. m_pkt.setParameter(0, 1); // number of directory entries to return
  368. m_pkt.setParameter(1, FileAttribute.Volume);
  369. // Pack the search string
  370. m_pkt.resetBytePointer();
  371. m_pkt.packByte(DataType.ASCII);
  372. m_pkt.packString("", false);
  373. // Append a null resume key, to indicate the start of a new search
  374. m_pkt.packByte(DataType.VariableBlock);
  375. m_pkt.packWord(0);
  376. m_pkt.setByteCount();
  377. // Send/receive the search SMB packet
  378. m_pkt.ExchangeSMB(this, m_pkt, true);
  379. // Unpack the volume label
  380. m_pkt.resetBytePointer();
  381. m_pkt.skipBytes(33); // data type byte + length word + offset to file name/volume label
  382. String label = m_pkt.unpackString(m_pkt.isUnicode());
  383. // Create the volume information object
  384. volInfo = new VolumeInfo(label);
  385. }
  386. else {
  387. // Create the transaction request
  388. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFileSys, null, 0, 2, 0);
  389. // Pack the parameter block
  390. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  391. paramBuf.putShort(FileInfoLevel.FSInfoQueryVolume);
  392. // Perform the get file system information transaction
  393. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  394. TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
  395. // Unpack the volume information
  396. if ( respBuf != null && respBuf.hasDataBuffer()) {
  397. // Get the data buffer
  398. DataBuffer dataBuf = respBuf.getDataBuffer();
  399. // Get the volume information
  400. long createTime = dataBuf.getLong();
  401. int serNo = dataBuf.getInt();
  402. int nameLen = dataBuf.getInt();
  403. if ( respBuf.isUnicode())
  404. nameLen = nameLen / 2;
  405. dataBuf.skipBytes(2);
  406. String label = dataBuf.getString(nameLen, respBuf.isUnicode());
  407. // Create the volume information
  408. volInfo = new VolumeInfo(label, serNo, NTTime.toSMBDate(createTime));
  409. }
  410. }
  411. // Return the volume information
  412. return volInfo;
  413. }
  414. /**
  415. * Check if the specified file name is a directory.
  416. *
  417. * @param dir Directory name string. If the directory name does not have a leading '\' the
  418. * current working directory for this session will be preprended to the string.
  419. * @return true if the specified file name is a directory, else false.
  420. * @exception java.io.IOException If an I/O error occurs.
  421. * @exception SMBException If an SMB level error occurs
  422. */
  423. public final boolean isDirectory(String dir)
  424. throws java.io.IOException, SMBException {
  425. // Allocate an SMB packet for the check directory request
  426. m_pkt.setFlags(getDefaultFlags());
  427. m_pkt.setFlags2(getDefaultFlags2());
  428. m_pkt.setCommand(PacketType.CheckDirectory);
  429. m_pkt.setUserId(this.getUserId());
  430. m_pkt.setTreeId(this.getTreeId());
  431. m_pkt.setParameterCount(0);
  432. // Build the remote directory tree relative path
  433. String pathName = dir;
  434. if ( pathName.startsWith("\\") == false)
  435. pathName = PCShare.makePath(getWorkingDirectory(), dir);
  436. // Pack the directory name
  437. m_pkt.resetBytePointer();
  438. m_pkt.packByte(DataType.ASCII);
  439. m_pkt.packString(pathName, m_pkt.isUnicode());
  440. m_pkt.setByteCount();
  441. // Send/receive the SMB check directory packet
  442. m_pkt.ExchangeSMB(this, m_pkt);
  443. // Check if a valid response was received, indicates the path is a directory
  444. return m_pkt.isValidResponse();
  445. }
  446. /**
  447. * Open a file on the remote file server.
  448. *
  449. * @param fname Remote file name string.
  450. * @param flags File open option flags.
  451. * @return SMBFile for the opened file, else null.
  452. * @exception java.io.IOException If an I/O error occurs
  453. * @exception SMBException If an SMB level error occurs
  454. */
  455. public final SMBFile OpenFile(String fname, int flags)
  456. throws java.io.IOException, SMBException {
  457. // Check if the path is a valid file path
  458. if ( isValidFilePath(fname) == false)
  459. throw new SMBException(SMBStatus.NTErr, SMBStatus.NTInvalidParameter);
  460. // Build the file name details
  461. String fileName = fname;
  462. if ( fileName.startsWith("\\") == false)
  463. fileName = PCShare.makePath(getWorkingDirectory(), fname);
  464. // Pre-NT dialect open file
  465. if ( getDialect() != Dialect.NT || isUnicode() == false) {
  466. // Initialize the SMB request to open an existing file
  467. m_pkt.setCommand(PacketType.OpenAndX);
  468. m_pkt.setFlags(getDefaultFlags());
  469. m_pkt.setFlags2(getDefaultFlags2());
  470. m_pkt.setUserId(this.getUserId());
  471. m_pkt.setTreeId(this.getTreeId());
  472. // Set the parameter words
  473. m_pkt.setParameterCount(15);
  474. m_pkt.setAndXCommand(0xFF); // no secondary command
  475. m_pkt.setParameter(1, 0); // offset to next command
  476. m_pkt.setParameter(2, 0x01); // return additional information
  477. m_pkt.setParameter(3, flags);
  478. m_pkt.setParameter(4, 0); // normal files only for now
  479. m_pkt.setParameter(5, 0); // file attributes
  480. m_pkt.setParameter(6, 0); // creation time
  481. m_pkt.setParameter(7, 0); // creation date
  482. // Default open mode is 'open if file exists'
  483. int openMode = FileAction.OpenIfExists;
  484. if ( AccessMode.getAccessMode(flags) == AccessMode.WriteOnly) {
  485. // Truncate the file if it exists, create file if it does not exist
  486. openMode = FileAction.CreateNotExist + FileAction.TruncateExisting;
  487. }
  488. else if ( AccessMode.getAccessMode(flags) == AccessMode.ReadWrite) {
  489. // Open the file if it exists, create the file if it does not exist
  490. openMode = FileAction.CreateNotExist + FileAction.OpenIfExists;
  491. }
  492. m_pkt.setParameter(8, openMode);
  493. m_pkt.setParameter(9, 0); // default allocation on create/truncate (long)
  494. m_pkt.setParameter(10, 0); // ... high word
  495. m_pkt.setParameter(11, 0);
  496. m_pkt.setParameter(12, 0);
  497. m_pkt.setParameter(13, 0);
  498. m_pkt.setParameter(14, 0);
  499. // Pack the file name string
  500. m_pkt.resetBytePointer();
  501. m_pkt.packString(fileName, m_pkt.isUnicode());
  502. m_pkt.setByteCount();
  503. // Send/receive the SMB file open packet
  504. m_pkt.ExchangeSMB(this, m_pkt, true);
  505. // Extract the file information from the received SMB packet
  506. int fid = m_pkt.getParameter(2);
  507. int attr = m_pkt.getParameter(3);
  508. int fsiz = (m_pkt.getParameter(7) << 16) + m_pkt.getParameter(6);
  509. // Create a file information object
  510. FileInfo finfo = new FileInfo(fname, fsiz, attr);
  511. // Create an SMB file object
  512. return new CIFSFile(this, finfo, fid);
  513. }
  514. else {
  515. // Default open mode is 'open if file exists'
  516. int openMode = FileAction.NTOpen;
  517. int accessMode = AccessMode.NTRead;
  518. if ( AccessMode.getAccessMode(flags) == AccessMode.WriteOnly) {
  519. // Truncate the file if it exists, create file if it does not exist
  520. openMode = FileAction.NTOverwriteIf;
  521. accessMode = AccessMode.NTWrite;
  522. }
  523. else if ( AccessMode.getAccessMode(flags) == AccessMode.ReadWrite) {
  524. // Open the file if it exists, create the file if it does not exist
  525. openMode = FileAction.NTOpenIf;
  526. accessMode = AccessMode.NTReadWrite;
  527. }
  528. // Open the remote file
  529. return NTCreate(fileName, accessMode, FileAttribute.NTNormal, SharingMode.READWRITEDELETE, openMode, 0, WinNT.CreateFile);
  530. }
  531. }
  532. /**
  533. * Rename a file, or set of files, on the remote file server.
  534. *
  535. * @param curnam Current file name string, may contain wildcards. If the path does not start
  536. * with a '\' the current working directory string will be preprended.
  537. * @param newnam New file name.
  538. * @param attr Search attributes, to determine which file(s) to rename.
  539. * @see org.alfresco.jlan.server.filesys.FileAttribute
  540. * @return true if the file rename request was successful, else false.
  541. * @exception java.io.IOException If an I/O error occurs.
  542. * @exception SMBException If an SMB level error occurs
  543. */
  544. public final boolean RenameFile(String curnam, String newnam, int attr)
  545. throws java.io.IOException, SMBException {
  546. // Create an SMB rename packet
  547. m_pkt.setFlags(getDefaultFlags());
  548. m_pkt.setFlags2(getDefaultFlags2());
  549. m_pkt.setCommand(PacketType.RenameFile);
  550. m_pkt.setUserId(this.getUserId());
  551. m_pkt.setTreeId(this.getTreeId());
  552. m_pkt.setParameterCount(1);
  553. m_pkt.setParameter(0, attr);
  554. // Add the current working directory path to the file names if they do not contain a path
  555. String fromName = curnam;
  556. if ( fromName.startsWith("\\") == false)
  557. fromName = PCShare.makePath(getWorkingDirectory(), curnam);
  558. String toName = newnam;
  559. if ( toName.startsWith("\\") == false)
  560. toName = PCShare.makePath(getWorkingDirectory(), newnam);
  561. // Pack the current and new file names
  562. m_pkt.resetBytePointer();
  563. m_pkt.packByte(DataType.ASCII);
  564. m_pkt.packString(fromName, m_pkt.isUnicode());
  565. m_pkt.packByte(DataType.ASCII);
  566. m_pkt.packString(toName, m_pkt.isUnicode());
  567. m_pkt.setByteCount();
  568. // Send/receive the SMB rename file(s) packet
  569. m_pkt.ExchangeSMB(this, m_pkt, true);
  570. // Check if we got a valid response
  571. if ( m_pkt.isValidResponse())
  572. return true;
  573. // Invalid rename request
  574. return false;
  575. }
  576. /**
  577. * Set file information for the specified file.
  578. *
  579. * @param fname File name of the file to set information for.
  580. * @param finfo File information containing the new values.
  581. * @exception java.io.IOException If an I/O error occurs.
  582. * @exception SMBException If an SMB level error occurs
  583. */
  584. public final void setFileInformation(String fname, FileInfo finfo)
  585. throws java.io.IOException, SMBException {
  586. // Create an SMB set file information packet
  587. m_pkt.setCommand(PacketType.SetFileAttributes);
  588. m_pkt.setUserId(this.getUserId());
  589. m_pkt.setTreeId(this.getTreeId());
  590. m_pkt.setFlags(getDefaultFlags());
  591. m_pkt.setFlags2(getDefaultFlags2());
  592. // Set the call parameters
  593. m_pkt.setParameterCount(8);
  594. m_pkt.setParameter(0, finfo.getFileAttributes());
  595. m_pkt.setParameter(1, finfo.getModifyDateTime().asSMBTime());
  596. m_pkt.setParameter(2, finfo.getModifyDateTime().asSMBDate());
  597. for (int i = 3; i < 8; i++)
  598. m_pkt.setParameter(i, 0);
  599. // Build the full path string
  600. String fileName = fname;
  601. if ( fname.startsWith("\\") == false)
  602. fileName = PCShare.makePath(getWorkingDirectory(), fname);
  603. // Pack the file name
  604. m_pkt.resetBytePointer();
  605. m_pkt.packByte(DataType.ASCII);
  606. m_pkt.packString(fileName, m_pkt.isUnicode());
  607. m_pkt.setByteCount();
  608. // Send/receive the SMB set file information packet
  609. m_pkt.ExchangeSMB(this, m_pkt, true);
  610. }
  611. /**
  612. * Set file information for the specified file, using the file id
  613. *
  614. * @param file File to set information for.
  615. * @param finfo File information containing the new values.
  616. * @exception java.io.IOException If an I/O error occurs.
  617. * @exception SMBException If an SMB level error occurs
  618. */
  619. public final void setFileInformation(SMBFile file, FileInfo finfo)
  620. throws java.io.IOException, SMBException {
  621. // Create an SMB set file information packet
  622. m_pkt.setCommand(PacketType.SetInformation2);
  623. m_pkt.setUserId(this.getUserId());
  624. m_pkt.setTreeId(this.getTreeId());
  625. m_pkt.setFlags(getDefaultFlags());
  626. m_pkt.setFlags2(getDefaultFlags2());
  627. // Set the call parameters
  628. m_pkt.setParameterCount(7);
  629. m_pkt.setParameter(0, file.getFileId());
  630. // Pack the new creation date/time, if available
  631. if ( finfo.hasCreationDateTime()) {
  632. m_pkt.setParameter(1, finfo.getCreationDateTime().asSMBTime());
  633. m_pkt.setParameter(2, finfo.getCreationDateTime().asSMBDate());
  634. }
  635. else {
  636. m_pkt.setParameter(1, 0);
  637. m_pkt.setParameter(2, 0);
  638. }
  639. // Pack the new access date/time, if available
  640. if ( finfo.hasAccessDateTime()) {
  641. m_pkt.setParameter(3, finfo.getAccessDateTime().asSMBTime());
  642. m_pkt.setParameter(4, finfo.getAccessDateTime().asSMBDate());
  643. }
  644. else {
  645. m_pkt.setParameter(3, 0);
  646. m_pkt.setParameter(4, 0);
  647. }
  648. // Pack the new modify date/time, if available
  649. if ( finfo.hasModifyDateTime()) {
  650. m_pkt.setParameter(5, finfo.getModifyDateTime().asSMBTime());
  651. m_pkt.setParameter(6, finfo.getModifyDateTime().asSMBDate());
  652. }
  653. else {
  654. m_pkt.setParameter(5, 0);
  655. m_pkt.setParameter(6, 0);
  656. }
  657. // Clear the byte count
  658. m_pkt.setByteCount(0);
  659. // Send/receive the SMB set file information packet
  660. m_pkt.ExchangeSMB(this, m_pkt, true);
  661. }
  662. /**
  663. * Set file attributes for the specified file, using the file name
  664. *
  665. * @param fname File name of the file to set information for.
  666. * @param attrib File attributes mask
  667. * @see org.alfresco.jlan.server.filesys.FileAttribute
  668. * @exception java.io.IOException If an I/O error occurs.
  669. * @exception SMBException If an SMB level error occurs
  670. */
  671. public final void setFileAttributes(String fname, int attrib)
  672. throws java.io.IOException, SMBException {
  673. // Create an SMB set file information packet
  674. m_pkt.setCommand(PacketType.SetFileAttributes);
  675. m_pkt.setUserId(this.getUserId());
  676. m_pkt.setTreeId(this.getTreeId());
  677. m_pkt.setFlags(getDefaultFlags());
  678. m_pkt.setFlags2(getDefaultFlags2());
  679. // Set the call parameters
  680. m_pkt.setParameterCount(8);
  681. m_pkt.setParameter(0, attrib);
  682. m_pkt.setParameter(1, 0);
  683. m_pkt.setParameter(2, 0);
  684. for (int i = 3; i < 8; i++)
  685. m_pkt.setParameter(i, 0);
  686. // Build the full path string
  687. String fileName = fname;
  688. if ( fname.startsWith("\\") == false)
  689. fileName = PCShare.makePath(getWorkingDirectory(), fname);
  690. // Pack the file name
  691. m_pkt.resetBytePointer();
  692. m_pkt.packByte(DataType.ASCII);
  693. m_pkt.packString(fileName, m_pkt.isUnicode());
  694. m_pkt.setByteCount();
  695. // Send/receive the SMB set file information packet
  696. m_pkt.ExchangeSMB(this, m_pkt, true);
  697. }
  698. /**
  699. * Start a search of the specified directory returning information for each file/directory
  700. * found.
  701. *
  702. * @param dir Directory to start searching. If the directory string does not start with a '\'
  703. * then the directory name is prepended with the current working directory.
  704. * @param attr Search attributes, to determine the types of files/directories returned. @see
  705. * org.alfresco.jlan.server.filesys.FileAttribute
  706. * @param level Information level required
  707. * @return SMBSearchContext for this search, else null
  708. * @exception java.io.IOException If an I/O error occurs
  709. * @exception SMBException If an SMB level error occurs
  710. */
  711. public final SearchContext StartSearch(String dir, int attr, int level)
  712. throws java.io.IOException, SMBException {
  713. // Create a new SMB search context
  714. TransSearchContext srch = new TransSearchContext(this);
  715. if ( srch == null)
  716. return null;
  717. // Start the search and return the search context
  718. srch.StartSearch(dir, attr, level);
  719. return srch;
  720. }
  721. /**
  722. * Perform an NTCreateAndX SMB to create/open a file or directory
  723. *
  724. * @param name File/directory name
  725. * @param access Desired access mode.
  726. * @see org.alfresco.jlan.server.filesys.AccessMode
  727. * @param attrib Required file attributes.
  728. * @see org.alfresco.jlan.server.filesys.FileAttribute
  729. * @param sharing Shared access mode
  730. * @param exists Action to take if file/directory exists.
  731. * @see org.alfresco.jlan.server.filesys.FileAction
  732. * @param initSize Initial file allocation size, in bytes
  733. * @param createOpt Create file options
  734. * @return CIFSFile
  735. * @exception IOException
  736. * @exception SMBException If an SMB level error occurs
  737. */
  738. public final CIFSFile NTCreate(String name, int access, int attrib, int sharing, int exists, long initSize, int createOpt)
  739. throws IOException, SMBException {
  740. // Call the main NTCreate method
  741. return NTCreateInternal(name, 0, access, attrib, sharing, exists, initSize, createOpt, true);
  742. }
  743. /**
  744. * Perform an NTCreateAndX SMB to create/open a file with an oplock
  745. *
  746. * @param name File/directory name
  747. * @param oplockFlags int
  748. * @param access Desired access mode.
  749. * @see org.alfresco.jlan.server.filesys.AccessMode
  750. * @param attrib Required file attributes.
  751. * @see org.alfresco.jlan.server.filesys.FileAttribute
  752. * @param sharing Shared access mode
  753. * @param exists Action to take if file/directory exists.
  754. * @see org.alfresco.jlan.server.filesys.FileAction
  755. * @param initSize Initial file allocation size, in bytes
  756. * @param createOpt Create file options
  757. * @return CIFSFile
  758. * @exception IOException
  759. * @exception SMBException If an SMB level error occurs
  760. */
  761. public final CIFSFile NTCreateWithOplock(String name, int oplockFlags, OplockInterface oplockIface,
  762. int access, int attrib, int sharing, int exists, long initSize, int createOpt)
  763. throws IOException, SMBException {
  764. // Call the main NTCreate method
  765. CIFSFile cifsFile = NTCreateInternal(name, oplockFlags, access, attrib, sharing, exists, initSize, createOpt, true);
  766. if ( cifsFile != null && cifsFile.getOplockType() != OpLock.TypeNone) {
  767. // Set the oplock interface
  768. cifsFile.setOplockInterface( oplockIface);
  769. // Add the file to the list of oplocked files, need to access the file to call
  770. // the oplock interface if an oplock break is received asynchronously from the server
  771. if ( m_oplockFiles == null)
  772. m_oplockFiles = new HashMap<Integer, CIFSFile>();
  773. m_oplockFiles.put( new Integer( cifsFile.getFileId()), cifsFile);
  774. }
  775. // Return the file
  776. return cifsFile;
  777. }
  778. /**
  779. * Perform an NT query security descriptor transaction for the specified file or directory
  780. *
  781. * @param fid File identifier, via SMBFile.getFileId() of an open file.
  782. * @param flags Security descriptor elements to return (Owner, Group, SACL, DACL).
  783. * @see org.alfresco.jlan.smb.nt.SecurityDescriptor
  784. * @return SecurityDescriptor
  785. * @exception IOException
  786. * @exception SMBException If an SMB level error occurs
  787. */
  788. public final SecurityDescriptor NTQuerySecurityDescriptor(int fid, int flags)
  789. throws IOException, SMBException {
  790. // Check if we have negotiated NT dialect
  791. if ( getDialect() != Dialect.NT)
  792. throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
  793. // Create the request transaction buffer
  794. TransactBuffer reqBuf = new TransactBuffer(PacketType.NTTransQuerySecurityDesc, null, 0, 8, 0);
  795. // Pack the parameter block for the request
  796. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  797. paramBuf.putShort(fid);
  798. paramBuf.putShort(0);
  799. paramBuf.putInt(flags);
  800. // Perform the query security descriptor transaction
  801. NTTransPacket ntPkt = new NTTransPacket();
  802. TransactBuffer respBuf = ntPkt.doTransaction(this, reqBuf);
  803. // Check if a security descriptor has been returned
  804. SecurityDescriptor secDesc = null;
  805. if ( respBuf != null && respBuf.hasDataBuffer()) {
  806. // Get the returned data
  807. DataBuffer dataBuf = respBuf.getDataBuffer();
  808. try {
  809. secDesc = new SecurityDescriptor();
  810. secDesc.loadDescriptor(dataBuf.getBuffer(), dataBuf.getOffset());
  811. }
  812. catch (LoadException ex) {
  813. secDesc = null;
  814. }
  815. }
  816. // Return the security descriptor
  817. return secDesc;
  818. }
  819. /**
  820. * Set the security descriptor for the specified file/directory
  821. *
  822. * @param fid File identifier, via SMBFile.getFileId() of an open file.
  823. * @param secdesc Security descriptor
  824. * @param flags Fields to set (Owner, Group, SACL, DACL).
  825. * @see org.alfresco.jlan.smb.nt.SecurityDescriptor
  826. * @exception IOException If a network error occurs
  827. * @exception SMBException If an SMB level error occurs
  828. * @exception SaveException If the security descriptor cannot be stored
  829. */
  830. public final void NTSetSecurityDescriptor(int fid, SecurityDescriptor secdesc, int flags)
  831. throws IOException, SMBException, SaveException {
  832. // Check if we have negotiated NT dialect
  833. if ( getDialect() != Dialect.NT)
  834. throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
  835. // Create the request transaction buffer
  836. TransactBuffer reqBuf = new TransactBuffer(PacketType.NTTransSetSecurityDesc, null, 0, 8, 65000);
  837. // Pack the parameter block
  838. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  839. paramBuf.putShort(fid);
  840. paramBuf.putShort(0);
  841. paramBuf.putInt(flags);
  842. // Pack the data block
  843. DataBuffer dataBuf = reqBuf.getDataBuffer();
  844. int len = secdesc.saveDescriptor(dataBuf.getBuffer(), 0);
  845. dataBuf.setLength(len);
  846. // Perform the set security descriptor transaction
  847. NTTransPacket ntPkt = new NTTransPacket();
  848. ntPkt.doTransaction(this, reqBuf);
  849. }
  850. /**
  851. * Add a change notification filter for the specified directory
  852. *
  853. * @param fid File id, from SMBFile.getFileId() of an open directory. The directory should be
  854. * opened using the NTCreate() method.
  855. * @param filter Directory watch filter flags. @see org.alfresco.jlan.client.nt.NotifyChange.
  856. * @param watchTree true to watch sub-directories, false to watch the specified directory only
  857. * @param handler DirectoryWatcher implementation. @see
  858. * org.alfresco.jlan.client.smb.DirectoryWatcher
  859. * @param autoResub true to automatically resubmit the notification filter after an event is
  860. * received
  861. * @return AsynchRequest
  862. * @exception IOException
  863. * @exception SMBException If an SMB level error occurs
  864. */
  865. public final AsynchRequest NTNotifyChange(int fid, int filter, boolean watchTree, DirectoryWatcher handler, boolean autoResub)
  866. throws IOException, SMBException {
  867. // Create an asynchronous request to hold the notify details
  868. NotifyChangeAsynchRequest areq = new NotifyChangeAsynchRequest(-1, fid, filter, watchTree, handler);
  869. areq.setAutoReset(autoResub);
  870. // Call the main notify change method to set the notify request
  871. return NTNotifyChange(areq);
  872. }
  873. /**
  874. * Add a change notification filter for the specified directory
  875. *
  876. * @param areq AsynchRequest
  877. * @return AsynchRequest
  878. * @exception IOException
  879. * @exception SMBException If an SMB level error occurs
  880. */
  881. public final AsynchRequest NTNotifyChange(AsynchRequest areq)
  882. throws IOException, SMBException {
  883. // Check if we have negotiated NT dialect
  884. if ( getDialect() != Dialect.NT)
  885. throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
  886. // Make sure the request is a notify change request
  887. if ( areq instanceof NotifyChangeAsynchRequest == false)
  888. throw new IOException("Invalid asynchronous request class, " + areq.getClass().getName());
  889. // Get the notify change asynchronous request
  890. NotifyChangeAsynchRequest nreq = (NotifyChangeAsynchRequest) areq;
  891. // Build the NT notify change transaction SMB packet
  892. NTTransPacket tpkt = new NTTransPacket();
  893. tpkt.setUserId(getUserId());
  894. tpkt.setTreeId(getTreeId());
  895. tpkt.setFlags(getDefaultFlags());
  896. tpkt.setFlags2(getDefaultFlags2());
  897. // Set the multiplex id to identify this notify request
  898. int mid = getNextMultiplexId();
  899. tpkt.setMultiplexId(mid);
  900. // Save the request id and clear the completed status of the request
  901. nreq.setId(mid);
  902. nreq.setCompleted(false);
  903. // Initialize the NT transaction packet
  904. tpkt.InitializeNTTransact(PacketType.NTTransNotifyChange, null, 0, null, 0, 4, 32, 0);
  905. tpkt.resetSetupPointer();
  906. tpkt.packInt(nreq.getFilter());
  907. tpkt.packWord(nreq.getFileId());
  908. tpkt.packByte(nreq.hasWatchTree() ? 1 : 0);
  909. tpkt.packByte(0);
  910. tpkt.setByteCount(0);
  911. // Send the notify change transaction
  912. //
  913. // Note: There is no response until the notification triggers
  914. tpkt.SendSMB(this);
  915. // Add the request to the pending list and return the request
  916. addAsynchronousRequest(nreq);
  917. return nreq;
  918. }
  919. /**
  920. * Cancel an outstanding request. Used to cancel change notifications.
  921. *
  922. * @param req AsynchRequest
  923. * @exception IOException
  924. * @exception SMBException If an SMB level error occurs
  925. */
  926. public final void NTCancel(AsynchRequest areq)
  927. throws IOException, SMBException {
  928. // Check if we have negotiated NT dialect
  929. if ( getDialect() != Dialect.NT)
  930. throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
  931. // Check if the request has auto-resubmit enabled, if so then disable the resubmit
  932. if ( areq.hasAutoReset())
  933. areq.setAutoReset(false);
  934. // Check if the request has already completed, if so then there is no need to cancel it
  935. if ( areq.hasCompleted())
  936. return;
  937. // Check if there is any data available for this network session, the request we are about
  938. // to
  939. // cancel may have just completed
  940. if ( getSession().hasData()) {
  941. // Clear out the recieve buffer
  942. pingServer();
  943. // Check if the request has now completed
  944. if ( areq.hasCompleted())
  945. return;
  946. }
  947. // Build the NTCancel SMB packet
  948. m_pkt.setFlags(getDefaultFlags());
  949. m_pkt.setFlags2(getDefaultFlags2());
  950. m_pkt.setCommand(PacketType.NTCancel);
  951. m_pkt.setUserId(getUserId());
  952. m_pkt.setTreeId(getTreeId());
  953. m_pkt.setMultiplexId(areq.getId());
  954. m_pkt.setParameterCount(0);
  955. m_pkt.setByteCount(0);
  956. // Send/receive the NT cancel request
  957. m_pkt.ExchangeSMB(this, m_pkt, false);
  958. // Check the return status
  959. boolean isValid = m_pkt.isValidResponse();
  960. if ( isValid == true)
  961. return;
  962. else if ( m_pkt.isLongErrorCode() && m_pkt.getLongErrorCode() == SMBStatus.NTCancelled)
  963. return;
  964. else {
  965. // Throw the SMB exception
  966. if ( m_pkt.hasLongErrorCode())
  967. throw new SMBException(SMBStatus.NTErr, m_pkt.getLongErrorCode());
  968. else
  969. throw new SMBException(m_pkt.getErrorClass(), m_pkt.getErrorCode());
  970. }
  971. }
  972. /**
  973. * NT I/O control
  974. *
  975. * @param ctrlCode int
  976. * @param fid int
  977. * @param fsctl boolean
  978. * @param data byte[]
  979. * @param dlen int
  980. * @param filter int
  981. * @return DataBuffer
  982. * @exception IOException
  983. * @exception SMBException If an SMB level error occurs
  984. */
  985. public final DataBuffer NTIOCtl(int ctrlCode, int fid, boolean fsctl, byte[] data, int dlen, int filter)
  986. throws IOException, SMBException {
  987. // Check if we have negotiated NT dialect
  988. if ( getDialect() != Dialect.NT)
  989. throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
  990. // Create the request transaction buffer
  991. TransactBuffer reqBuf = new TransactBuffer(PacketType.NTTransIOCtl, 8, 0, data, 0, dlen);
  992. // Pack the setup block
  993. DataBuffer setupBuf = reqBuf.getSetupBuffer();
  994. setupBuf.putInt(ctrlCode);
  995. setupBuf.putShort(fid);
  996. setupBuf.putByte(fsctl ? 1 : 0);
  997. setupBuf.putByte(filter);
  998. // Perform the I/O control transaction
  999. NTTransPacket ntPkt = new NTTransPacket();
  1000. TransactBuffer respBuf = ntPkt.doTransaction(this, reqBuf);
  1001. // Check if there is any return data
  1002. if ( respBuf != null)
  1003. return respBuf.getDataBuffer();
  1004. return null;
  1005. }
  1006. /**
  1007. * Get file information for the specified open file/directory, returning the requested
  1008. * information level
  1009. *
  1010. * @param fid File id for the file or directory, from SMBFile.getFileId().
  1011. * @param level Information level. @see org.alfresco.jlan.smb.FileInfoLevel
  1012. * @return FileInfo
  1013. * @exception IOException
  1014. * @exception SMBException If an SMB level error occurs
  1015. */
  1016. public final FileInfo NTGetFileInformation(int fid, int level)
  1017. throws IOException, SMBException {
  1018. // Create the request transaction buffer
  1019. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFile, null, 0, 4, 0);
  1020. // Pack the parameter block
  1021. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  1022. paramBuf.putShort(fid);
  1023. paramBuf.putShort(level);
  1024. // Perform the get file information transaction
  1025. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  1026. TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
  1027. // Unpack the received file information data
  1028. FileInfo finfo = null;
  1029. if ( respBuf != null && respBuf.hasDataBuffer()) {
  1030. // Unpack the file information
  1031. DataBuffer buf = respBuf.getDataBuffer();
  1032. switch (level) {
  1033. case FileInfoLevel.PathStandard:
  1034. finfo = FileInfoPacker.unpackFileInfoStandard("", buf, false);
  1035. break;
  1036. case FileInfoLevel.PathQueryEASize:
  1037. finfo = FileInfoPacker.unpackFileInfoStandard("", buf, true);
  1038. break;
  1039. case FileInfoLevel.PathAllEAs:
  1040. break;
  1041. case FileInfoLevel.PathFileBasicInfo:
  1042. finfo = FileInfoPacker.unpackQueryBasicInfo("", buf);
  1043. break;
  1044. case FileInfoLevel.PathFileStandardInfo:
  1045. finfo = FileInfoPacker.unpackQueryStandardInfo("", buf);
  1046. break;
  1047. case FileInfoLevel.PathFileEAInfo:
  1048. finfo = FileInfoPacker.unpackQueryEAInfo("", buf);
  1049. break;
  1050. case FileInfoLevel.PathFileNameInfo:
  1051. finfo = FileInfoPacker.unpackQueryNameInfo(buf, respBuf.isUnicode());
  1052. break;
  1053. case FileInfoLevel.PathFileAllInfo:
  1054. finfo = FileInfoPacker.unpackQueryAllInfo(buf, respBuf.isUnicode());
  1055. break;
  1056. case FileInfoLevel.PathFileAltNameInfo:
  1057. finfo = FileInfoPacker.unpackQueryNameInfo(buf, respBuf.isUnicode());
  1058. break;
  1059. case FileInfoLevel.PathFileStreamInfo:
  1060. finfo = FileInfoPacker.unpackQueryStreamInfo("", buf, respBuf.isUnicode());
  1061. break;
  1062. case FileInfoLevel.PathFileCompressionInfo:
  1063. finfo = FileInfoPacker.unpackQueryCompressionInfo("", buf);
  1064. break;
  1065. }
  1066. }
  1067. // If the file information is valid, set the file id so the file information can be used
  1068. // to set information
  1069. if ( finfo != null)
  1070. finfo.setFileId(fid);
  1071. // Return the file information
  1072. return finfo;
  1073. }
  1074. /**
  1075. * Get file information for the specified open file/directory, returning the requested
  1076. * information level
  1077. *
  1078. * @param fid File id for the file or directory, from SMBFile.getFileId().
  1079. * @param level Information level. @see org.alfresco.jlan.smb.FileInfoLevel
  1080. * @return TransactBuffer
  1081. * @exception IOException
  1082. * @exception SMBException If an SMB level error occurs
  1083. */
  1084. public final TransactBuffer NTGetFileInformationRaw(int fid, int level)
  1085. throws IOException, SMBException {
  1086. // Create the request transaction buffer
  1087. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFile, null, 0, 4, 0);
  1088. // Pack the parameter block
  1089. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  1090. paramBuf.putShort(fid);
  1091. paramBuf.putShort(level);
  1092. // Perform the get file information transaction
  1093. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  1094. return tpkt.doTransaction(this, reqBuf);
  1095. }
  1096. /**
  1097. * Set file information that allows setting different information levels
  1098. *
  1099. * @param finfo FileInfo
  1100. * @param level Information level. @see org.alfresco.jlan.smb.FileInfoLevel
  1101. * @exception IOException
  1102. * @exception SMBException If an SMB level error occurs
  1103. */
  1104. public final void NTSetFileInformation(FileInfo finfo, int level)
  1105. throws IOException, SMBException {
  1106. // Create the request transaction buffer
  1107. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2SetFile, null, 0, 6, 65000);
  1108. // Pack the parameter block
  1109. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  1110. paramBuf.putShort(finfo.getFileId());
  1111. paramBuf.putShort(level);
  1112. paramBuf.putShort(0);
  1113. // Pack the file information into the data buffer
  1114. DataBuffer dataBuf = reqBuf.getDataBuffer();
  1115. switch (level) {
  1116. case FileInfoLevel.SetStandard:
  1117. FileInfoPacker.packFileInfoStandard(finfo, dataBuf, false);
  1118. break;
  1119. case FileInfoLevel.SetQueryEASize:
  1120. FileInfoPacker.packFileInfoStandard(finfo, dataBuf, true);
  1121. break;
  1122. case FileInfoLevel.SetBasicInfo:
  1123. FileInfoPacker.packFileBasicInfo(finfo, dataBuf);
  1124. break;
  1125. case FileInfoLevel.SetDispositionInfo:
  1126. break;
  1127. case FileInfoLevel.SetAllocationInfo:
  1128. break;
  1129. case FileInfoLevel.SetEndOfFileInfo:
  1130. break;
  1131. }
  1132. ;
  1133. // Perform the get file information transaction
  1134. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  1135. tpkt.doTransaction(this, reqBuf);
  1136. }
  1137. /**
  1138. * Set the delete on close flag for an open file
  1139. *
  1140. * @param fid File id for the file or directory, from SMBFile.getFileId().
  1141. * @param delFlag true to delete the file on close, or false to clear a previous delete on close
  1142. * request
  1143. * @exception IOException
  1144. * @exception SMBException If an SMB level error occurs
  1145. */
  1146. public final void NTSetDeleteOnClose(int fid, boolean delFlag)
  1147. throws IOException, SMBException {
  1148. // Create the data block for the set file disposition info level (0x102)
  1149. byte[] dblock = new byte[4];
  1150. dblock[0] = delFlag == true ? (byte) 1 : (byte) 0;
  1151. // Set the delete on close setting for the open file
  1152. NTSetFileInformationRaw(fid, dblock, 2, 0x102);
  1153. }
  1154. /**
  1155. * Set the end of file position for the open file
  1156. *
  1157. * @param fid File id for the file or directory, from SMBFile.getFileId().
  1158. * @param pos New end of file position
  1159. * @exception IOException
  1160. * @exception SMBException If an SMB level error occurs
  1161. */
  1162. public final void NTSetEndOfFile(int fid, long pos)
  1163. throws IOException, SMBException {
  1164. // Create the data block for the set end of file info level (0x104)
  1165. byte[] dblock = new byte[8];
  1166. DataPacker.putIntelLong(pos, dblock, 0);
  1167. // Set the end of file position for the open file
  1168. NTSetFileInformationRaw(fid, dblock, 8, 0x104);
  1169. }
  1170. /**
  1171. * Set the file allocation size for the open file
  1172. *
  1173. * @param fid File id for the file or directory, from SMBFile.getFileId().
  1174. * @param alloc New file allocation size
  1175. * @exception IOException
  1176. * @exception SMBException If an SMB level error occurs
  1177. */
  1178. public final void NTSetFileAllocation(int fid, long alloc)
  1179. throws IOException, SMBException {
  1180. // Create the data block for the set file allocation info level (0x103)
  1181. byte[] dblock = new byte[8];
  1182. DataPacker.putIntelLong(alloc, dblock, 0);
  1183. // Set the file allocation for the open file
  1184. NTSetFileInformationRaw(fid, dblock, 8, 0x103);
  1185. }
  1186. /**
  1187. * Set file information that allows setting different information levels
  1188. *
  1189. * @param fid File id for the file or directory, from SMBFile.getFileId().
  1190. * @param data Raw file information data block.
  1191. * @param dlen Raw data block length.
  1192. * @param level File information level. @see org.alfresco.jlan.smb.FileInfoLevel
  1193. * @exception IOException
  1194. * @exception SMBException If an SMB level error occurs
  1195. */
  1196. private final void NTSetFileInformationRaw(int fid, byte[] data, int dlen, int level)
  1197. throws IOException, SMBException {
  1198. // Create the request transaction buffer
  1199. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2SetFile, 0, 6, data, 0, dlen);
  1200. // Pack the parameter block
  1201. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  1202. paramBuf.putShort(fid);
  1203. paramBuf.putShort(level);
  1204. paramBuf.putShort(0);
  1205. // Perform the get file information transaction
  1206. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  1207. tpkt.doTransaction(this, reqBuf);
  1208. }
  1209. /**
  1210. * Get the device information
  1211. *
  1212. * @return DeviceInfo @see org.alfresco.jlan.client.info.DeviceInfo
  1213. * @exception IOException
  1214. * @exception SMBException
  1215. */
  1216. public final DeviceInfo NTGetDeviceInfo()
  1217. throws IOException, SMBException {
  1218. // Create the request transaction buffer
  1219. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFileSys, null, 0, 2, 0);
  1220. // Pack the parameter block
  1221. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  1222. paramBuf.putShort(FileInfoLevel.FSInfoQueryDevice);
  1223. // Perform the get file information transaction
  1224. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  1225. TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
  1226. // Unpack the received device information data
  1227. DeviceInfo devInfo = null;
  1228. if ( respBuf != null && respBuf.hasDataBuffer()) {
  1229. // Unpack the device information
  1230. DataBuffer buf = respBuf.getDataBuffer();
  1231. int typ = buf.getInt();
  1232. int chr = buf.getInt();
  1233. // Return the device information
  1234. devInfo = new DeviceInfo(typ, chr);
  1235. }
  1236. // Return the device information
  1237. return devInfo;
  1238. }
  1239. /**
  1240. * Get the device attributes information
  1241. *
  1242. * @return DeviceAttributesInfo
  1243. * @exception IOException
  1244. * @exception SMBException
  1245. */
  1246. public final DeviceAttributesInfo NTGetDeviceAttributes()
  1247. throws IOException, SMBException {
  1248. // Create the request transaction buffer
  1249. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryFileSys, null, 0, 2, 0);
  1250. // Pack the parameter block
  1251. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  1252. paramBuf.putShort(FileInfoLevel.FSInfoQueryAttribute);
  1253. // Perform the get file information transaction
  1254. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  1255. TransactBuffer respBuf = tpkt.doTransaction(this, reqBuf);
  1256. // Unpack the received device attribute information data
  1257. DeviceAttributesInfo attrInfo = null;
  1258. if ( respBuf != null && respBuf.hasDataBuffer()) {
  1259. // Unpack the device attribute information
  1260. DataBuffer buf = respBuf.getDataBuffer();
  1261. int attr = buf.getInt();
  1262. int maxLen = buf.getInt();
  1263. int lblLen = buf.getInt();
  1264. if ( respBuf.isUnicode())
  1265. lblLen = lblLen / 2;
  1266. String label = buf.getString(lblLen, respBuf.isUnicode());
  1267. // Return the device attributes
  1268. attrInfo = new DeviceAttributesInfo(attr, maxLen, label);
  1269. }
  1270. // Return the device attribute information
  1271. return attrInfo;
  1272. }
  1273. /**
  1274. * Get file information for the specified file.
  1275. *
  1276. * @param fname File name of the file to return information for.
  1277. * @param level Information level required. @see org.alfresco.jlan.smb.FileInfoLevel
  1278. * @return TransactBuffer
  1279. * @exception java.io.IOException If an I/O error occurs.
  1280. * @exception java.io.FileNotFoundException If the remote file does not exist.
  1281. * @exception SMBException If an SMB level error occurs
  1282. */
  1283. public final TransactBuffer getFileInformationRaw(String fname, int level)
  1284. throws java.io.IOException, java.io.FileNotFoundException, SMBException {
  1285. // Build the file name/path string
  1286. String pathName = fname;
  1287. if ( pathName.startsWith("\\") == false)
  1288. pathName = PCShare.makePath(getWorkingDirectory(), fname);
  1289. // Create the request transaction buffer
  1290. TransactBuffer reqBuf = new TransactBuffer(PacketType.Trans2QueryPath, null, 0, 512, 0);
  1291. // Pack the parameter block
  1292. DataBuffer paramBuf = reqBuf.getParameterBuffer();
  1293. paramBuf.putShort(level);
  1294. paramBuf.putInt(0);
  1295. paramBuf.putString(pathName, isUnicode());
  1296. // Perform the get file information transaction
  1297. TransPacket tpkt = new TransPacket(m_pkt.getBuffer());
  1298. return tpkt.doTransaction(this, reqBuf);
  1299. }
  1300. /**
  1301. * Return the details for a symlink file/folder
  1302. *
  1303. * @param linkPath String
  1304. * @return SymLink
  1305. * @exception Exception
  1306. */
  1307. public final SymLink getSymLinkDetails(String linkPath)
  1308. throws Exception {
  1309. // Open the symlink file
  1310. CIFSFile linkFile = NTCreateInternal(linkPath, 0, AccessMode.NTRead + AccessMode.NTReadControl + AccessMode.NTReadAttrib
  1311. + AccessMode.NTReadEA, FileAttribute.NTNormal, SharingMode.READWRITE, FileAction.NTOpen, 0,
  1312. WinNT.CreateReparsePoint, false);
  1313. SymLink symLink = null;
  1314. Exception retError = null;
  1315. try {
  1316. // Make sure the file is a reparse point
  1317. if ( linkFile.isReparsePoint()) {
  1318. // Get the symlink details
  1319. int ioctlCode = NTIOCtl.makeControlCode(NTIOCtl.DeviceFileSystem, NTIOCtl.FsCtlGetReparsePoint,
  1320. NTIOCtl.MethodBuffered, NTIOCtl.AccessAny);
  1321. DataBuffer linkBuf = NTIOCtl(ioctlCode, linkFile.getFileId(), true, null, 0, 0);
  1322. // Parse the returned structure
  1323. symLink = new SymLink(linkBuf);
  1324. }
  1325. else {
  1326. // Return an exception
  1327. retError = new IOException("Not a reparse point, " + linkPath);
  1328. }
  1329. }
  1330. catch (Exception ex) {
  1331. // Save the error
  1332. retError = ex;
  1333. }
  1334. finally {
  1335. // Close the link file
  1336. try {
  1337. linkFile.Close();
  1338. }
  1339. catch (Exception ex) {
  1340. }
  1341. }
  1342. // Check if there is an error to return
  1343. if ( retError != null)
  1344. throw retError;
  1345. // Return the symlink details
  1346. return symLink;
  1347. }
  1348. /**
  1349. * Process incoming data checking for asynchronous response packets from the server
  1350. *
  1351. * @param waitTime Receive timeout in milliseconds, zero for no timeout or -1 to not wait for
  1352. * data
  1353. * @exception IOException
  1354. * @exception SMBException
  1355. */
  1356. public final void checkForAsynchReceive(int waitTime)
  1357. throws IOException, SMBException {
  1358. // Check if there is any data in the socket receive buffer, if the caller does not want
  1359. // to wait for a packet then return immediately
  1360. if ( waitTime == -1 && getSession().hasData() == false) {
  1361. // Check if we need to send an echo packet to the server to keep the SMB session alive
  1362. if ( (m_pkt.getLastPacketSendTime() + SessionKeepAlive) < System.currentTimeMillis())
  1363. pingServer();
  1364. return;
  1365. }
  1366. // Wait for an asynchronous response from the server
  1367. m_pkt.ReceiveAsynchSMB(this, waitTime == -1 ? 0 : waitTime);
  1368. // Check if we need to send an echo packet to the server to keep the SMB session alive.
  1369. //
  1370. // The asynchronous receive will usually result in the request being reset on the server, if
  1371. // not then we may need to send an echo request.
  1372. if ( (m_pkt.getLastPacketSendTime() + SessionKeepAlive) < System.currentTimeMillis())
  1373. pingServer();
  1374. }
  1375. /**
  1376. * Refresh the file information for an open file
  1377. *
  1378. * @param smbFile SMBFile
  1379. */
  1380. public void refreshFileInformation( SMBFile smbFile)
  1381. throws IOException, SMBException {
  1382. }
  1383. /**
  1384. * Process an asynchronous response packet
  1385. *
  1386. * @param pkt SMBPacket
  1387. */
  1388. protected void processAsynchResponse(SMBPacket pkt) {
  1389. // Check for a locking request from the server, an oplock break
  1390. if ( pkt.isRequest() == true && pkt.getCommand() == PacketType.LockingAndX) {
  1391. // Unpack the file id and flags
  1392. int fileId = pkt.getParameter( 2);
  1393. int flags = pkt.getParameter( 3);
  1394. // Check for an oplock break
  1395. if ( m_oplockFiles != null && ( flags & LockingAndX.OplockBreak) != 0) {
  1396. try {
  1397. // Find the oplocked file
  1398. CIFSFile cifsFile = m_oplockFiles.get( new Integer( fileId));
  1399. int breakToOpLock = OpLock.TypeNone;
  1400. if ( cifsFile != null) {
  1401. // Check if the file has an oplock callback interface
  1402. if ( cifsFile.getOplockInterface() != null) {
  1403. // Call the oplock interface
  1404. breakToOpLock = cifsFile.getOplockInterface().oplockBreak( cifsFile);
  1405. }
  1406. else {
  1407. // Flush any pending data on the file
  1408. cifsFile.Flush();
  1409. }
  1410. }
  1411. // Check if an oplock break response should be sent
  1412. if ( cifsFile.getOplockInterface().sendAutomaticBreakResponse() == true) {
  1413. // Build an oplock break response
  1414. SMBPacket respPkt = new SMBPacket( 128);
  1415. respPkt.setCommand(PacketType.LockingAndX);
  1416. respPkt.setUserId(this.getUserId());
  1417. respPkt.setTreeId(this.getTreeId());
  1418. respPkt.setFlags(getDefaultFlags() + SMBPacket.FLG_RESPONSE);
  1419. respPkt.setFlags2(getDefaultFlags2());
  1420. respPkt.setParameterCount(8);
  1421. respPkt.setAndXCommand( PacketType.NoChainedCommand);
  1422. respPkt.setParameter(1, 0); // AndX offset
  1423. respPkt.setParameter(2, fileId);
  1424. // Break the oplock, or break to a level II shared oplock
  1425. if ( breakToOpLock == OpLock.TypeLevelII)
  1426. respPkt.setParameter(3, LockingAndX.OplockBreak + LockingAndX.Level2OpLock);
  1427. else
  1428. respPkt.setParameter(3, LockingAndX.OplockBreak);
  1429. respPkt.setParameterLong(4, 0); // timeout
  1430. respPkt.setParameter(6, 0); // number of unlocks
  1431. respPkt.setParameter(7, 0); // number of locks
  1432. respPkt.setByteCount( 0);
  1433. // Send the oplock break to the server
  1434. //
  1435. // Note: The response flag must be set, and we do not expect a response from the server
  1436. respPkt.SendSMB( this);
  1437. // Set the new oplock type on the file
  1438. cifsFile.setOplockType( breakToOpLock);
  1439. cifsFile.setOplockInterface( null);
  1440. }
  1441. }
  1442. catch (Exception ex) {
  1443. }
  1444. }
  1445. }
  1446. else {
  1447. // Check if there are any pending asynchronous requests queued
  1448. if ( m_asynchRequests == null || m_asynchRequests.size() == 0)
  1449. return;
  1450. // Find the matching asynchronous request and remove from the pending list
  1451. AsynchRequest areq = removeAsynchronousRequest(pkt.getMultiplexId());
  1452. if ( areq == null)
  1453. return;
  1454. // Mark the asynchronous request as completed
  1455. areq.setCompleted(true);
  1456. // Pass the packet to the asynchronous request for processing
  1457. areq.processResponse(this, pkt);
  1458. // Check if the request should be automatically resubmitted
  1459. if ( areq.hasAutoReset()) {
  1460. // Resubmit the request
  1461. if ( areq.resubmitRequest(this, null) == true)
  1462. addAsynchronousRequest(areq);
  1463. }
  1464. }
  1465. }
  1466. /**
  1467. * Add an asynchronous request to the list of pending requests
  1468. *
  1469. * @param req AsynchRequest
  1470. */
  1471. protected final void addAsynchronousRequest(AsynchRequest req) {
  1472. // Check if the asynchronous request list has been allocated
  1473. if ( m_asynchRequests == null)
  1474. m_asynchRequests = new ArrayList<AsynchRequest>();
  1475. // Add the request to the list
  1476. m_asynchRequests.add(req);
  1477. }
  1478. /**
  1479. * Remove an asynchronous request from the pending list
  1480. *
  1481. * @param id int
  1482. * @return AsynchRequest
  1483. */
  1484. protected final AsynchRequest removeAsynchronousRequest(int id) {
  1485. // Check if the list is valid
  1486. if ( m_asynchRequests == null)
  1487. return null;
  1488. // Find the request
  1489. AsynchRequest areq = null;
  1490. int idx = 0;
  1491. while (idx < m_asynchRequests.size() && areq == null) {
  1492. // Get the current request and check if it is the required request
  1493. AsynchRequest curReq = m_asynchRequests.get(idx);
  1494. if ( curReq.getId() == id)
  1495. areq = curReq;
  1496. else
  1497. idx++;
  1498. }
  1499. // Remove the request from the list
  1500. if ( areq != null)
  1501. m_asynchRequests.remove(areq);
  1502. // Return the removed request
  1503. return areq;
  1504. }
  1505. /**
  1506. * Remove an asynchronous request from the pending list
  1507. *
  1508. * @param req AsynchRequest
  1509. * @return AsynchRequest
  1510. */
  1511. protected final AsynchRequest removeAsynchronousRequest(AsynchRequest req) {
  1512. // Check if the list is valid
  1513. if ( m_asynchRequests == null)
  1514. return null;
  1515. // Remove the request from the list
  1516. m_asynchRequests.remove(req);
  1517. return req;
  1518. }
  1519. /**
  1520. * Perform an NTCreateAndX SMB to create/open a file or directory
  1521. *
  1522. * @param name File/directory name
  1523. * @param createFlags int
  1524. * @param access Desired access mode.
  1525. * @see org.alfresco.jlan.server.filesys.AccessMode
  1526. * @param attrib Required file attributes.
  1527. * @see org.alfresco.jlan.server.filesys.FileAttribute
  1528. * @param sharing Shared access mode
  1529. * @param exists Action to take if file/directory exists.
  1530. * @see org.alfresco.jlan.server.filesys.FileAction
  1531. * @param initSize Initial file allocation size, in bytes
  1532. * @param createOpt Create file options
  1533. * @param throwErr Throw errors from the CIFS packet exchange
  1534. * @return CIFSFile
  1535. * @exception IOException
  1536. * @exception SMBException If an SMB level error occurs
  1537. */
  1538. protected final CIFSFile NTCreateInternal(String name, int createFlags, int access, int attrib, int sharing, int exists, long initSize,
  1539. int createOpt, boolean throwErr)
  1540. throws IOException, SMBException {
  1541. // Check if we have negotiated NT dialect
  1542. if ( getDialect() != Dialect.NT)
  1543. throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
  1544. // Build the NTCreateAndX SMB packet
  1545. m_pkt.setFlags(getDefaultFlags());
  1546. m_pkt.setFlags2(getDefaultFlags2());
  1547. m_pkt.setCommand(PacketType.NTCreateAndX);
  1548. m_pkt.setUserId(getUserId());
  1549. m_pkt.setTreeId(getTreeId());
  1550. m_pkt.setParameterCount(24);
  1551. m_pkt.resetParameterPointer();
  1552. m_pkt.packByte(0xFF); // no chained command
  1553. m_pkt.packByte(0); // reserved
  1554. m_pkt.packWord(0); // AndX offset
  1555. m_pkt.packByte(0); // reserved
  1556. m_pkt.packWord((name.length() * 2) + 2); // name length in bytes, inc null
  1557. m_pkt.packInt(createFlags); // oplocks/extended response
  1558. m_pkt.packInt(0); // root FID
  1559. m_pkt.packInt(access); // desired access mode
  1560. m_pkt.packLong(initSize); // allocation size
  1561. m_pkt.packInt(attrib); // file attributes
  1562. m_pkt.packInt(sharing); // share access mode
  1563. m_pkt.packInt(exists); // action to take if file exists
  1564. m_pkt.packInt(createOpt); // file create options
  1565. m_pkt.packInt(2); // impersonation level, 0=anonymous, 2=impersonation
  1566. m_pkt.packByte(0); // security flags
  1567. m_pkt.resetBytePointer();
  1568. m_pkt.packString(name, m_pkt.isUnicode());
  1569. m_pkt.setByteCount();
  1570. // Send/receive the NT create andX request
  1571. m_pkt.ExchangeSMB(this, m_pkt, throwErr);
  1572. // Unpack the file/directory details
  1573. m_pkt.resetParameterPointer();
  1574. m_pkt.skipBytes(4);
  1575. int oplockTyp = m_pkt.unpackByte();
  1576. int fid = m_pkt.unpackWord();
  1577. int createAction = m_pkt.unpackInt();
  1578. long createTime = m_pkt.unpackLong();
  1579. long lastAccessTime = m_pkt.unpackLong();
  1580. long lastWriteTime = m_pkt.unpackLong();
  1581. long changeTime = m_pkt.unpackLong();
  1582. int attr = m_pkt.unpackInt();
  1583. long allocSize = m_pkt.unpackLong();
  1584. long eofOffset = m_pkt.unpackLong();
  1585. int devType = m_pkt.unpackWord();
  1586. // Create the file information
  1587. FileInfo finfo = new FileInfo(name, eofOffset, attr);
  1588. finfo.setFileId(fid);
  1589. // Convert the granted oplock type to internal type
  1590. if ( oplockTyp == WinNT.GrantedOplockBatch)
  1591. oplockTyp = OpLock.TypeBatch;
  1592. else if ( oplockTyp == WinNT.GrantedOplockExclusive)
  1593. oplockTyp = OpLock.TypeExclusive;
  1594. else if ( oplockTyp == WinNT.GrantedOplockLevelII)
  1595. oplockTyp = OpLock.TypeLevelII;
  1596. else
  1597. oplockTyp = OpLock.TypeNone;
  1598. // Create the file object
  1599. return new CIFSFile(this, finfo, fid, oplockTyp);
  1600. }
  1601. /**
  1602. * File closed, remove from the oplocked file list
  1603. *
  1604. * @param cifsFile CIFSFile
  1605. */
  1606. protected final void fileClosed( CIFSFile cifsFile) {
  1607. // Check if there are any oplocked files
  1608. if ( m_oplockFiles == null || m_oplockFiles.size() == 0)
  1609. return;
  1610. // Remove the file from the oplocked list
  1611. m_oplockFiles.remove( new Integer( cifsFile.getFileId()));
  1612. }
  1613. }