DataPipeFile.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  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.net.SocketTimeoutException;
  22. import org.alfresco.jlan.client.info.FileInfo;
  23. import org.alfresco.jlan.netbios.RFCNetBIOSProtocol;
  24. import org.alfresco.jlan.smb.Dialect;
  25. import org.alfresco.jlan.smb.LockingAndX;
  26. import org.alfresco.jlan.smb.PacketType;
  27. import org.alfresco.jlan.smb.SMBDate;
  28. import org.alfresco.jlan.smb.SMBException;
  29. import org.alfresco.jlan.smb.SMBStatus;
  30. import org.alfresco.jlan.smb.SeekType;
  31. /**
  32. * SMB CIFS Data Pipe File Class
  33. *
  34. * <p>An SMB file provides read and/or write access to a remote named pipe.
  35. *
  36. * @author gkspencer
  37. */
  38. public final class DataPipeFile extends SMBFile {
  39. // Size of protocol packet to allocate
  40. private static final int DataSize = 4000;
  41. private static final int PacketSize = DataSize + 128;
  42. // Offset that the write data is placed within the write SMB packet, including protocol header of 4 bytes, and
  43. // padding byte count to word align the data
  44. private static final int WriteDataOffset = 64;
  45. private static final int WriteDataPadding = 1;
  46. // Maximum file offset for 32bit files
  47. private static final long Maximum32BitOffset = 0x0FFFFFFFFL;
  48. // state flag to indicate that the pipe is broken
  49. private static final int PipeBroken = 0x1000;
  50. // No timeout for read
  51. public static final int NoTimeout = 0;
  52. // Flag to indicate we are using NT dialect SMBs
  53. private boolean m_NTdialect;
  54. /**
  55. * Class constructor
  56. *
  57. * @param sess Session that this file is associated with
  58. * @param finfo File information for the new file
  59. * @param fid File identifier for this file
  60. */
  61. protected DataPipeFile(Session sess, FileInfo finfo, int fid) {
  62. super(sess, finfo, fid);
  63. // Set the NT dialect flag
  64. if ( sess.getDialect() == Dialect.NT)
  65. m_NTdialect = true;
  66. else
  67. m_NTdialect = false;
  68. }
  69. /**
  70. * Close the remote file.
  71. *
  72. * @param wrDateTime Set the last write date/time, or null to let the server set the date/time
  73. * @exception java.io.IOException If an I/O error occurs
  74. * @exception SMBException If an SMB level error occurs
  75. */
  76. public final void Close(SMBDate wrDateTime)
  77. throws java.io.IOException, SMBException {
  78. // Flush any buffered write data
  79. if ( m_txlen > 0)
  80. Flush();
  81. // Determine which packet to use to send the close file SMB
  82. SMBPacket pkt = new SMBPacket();
  83. pkt.setUserId(m_sess.getUserId());
  84. pkt.setTreeId(m_sess.getTreeId());
  85. // Close the remote file.
  86. pkt.setCommand(PacketType.CloseFile);
  87. pkt.setParameterCount(3);
  88. pkt.setParameter(0, m_FID);
  89. // Do not set a modified date/time
  90. pkt.setParameter(1, 0);
  91. pkt.setParameter(2, 0);
  92. // Indicate that the file has been closed
  93. this.setStateFlag(SMBFile.Closed, true);
  94. // Exchange the close file SMB packet with the file server
  95. try {
  96. pkt.ExchangeSMB(m_sess, pkt);
  97. }
  98. catch (java.io.IOException ex) {
  99. return;
  100. }
  101. // Release the transmit/receive packets
  102. m_rxpkt = null;
  103. m_txpkt = null;
  104. // Close the associated session
  105. getSession().CloseSession();
  106. return;
  107. }
  108. /**
  109. * Flush data to the remote file.
  110. *
  111. * @exception java.io.IOException If an I/O error occurs
  112. * @exception SMBException If an SMB level error occurs
  113. */
  114. public final void Flush()
  115. throws java.io.IOException, SMBException {
  116. // Check if there is any buffered write data
  117. if ( m_txlen > 0)
  118. WriteData();
  119. }
  120. /**
  121. * Read a block of data from the file.
  122. *
  123. * @param buf Byte buffer to receive the data.
  124. * @param siz Maximum length of data to receive.
  125. * @param offset Offset within buffer to place received data.
  126. * @return Actual length of data received.
  127. * @exception java.io.IOException If an I/O error occurs
  128. * @exception SMBException If an SMB level error occurs
  129. */
  130. public final int Read(byte[] buf, int siz, int offset)
  131. throws java.io.IOException, SMBException {
  132. // Read from the pipe
  133. return Read(buf, siz, offset, NoTimeout, siz);
  134. }
  135. /**
  136. * Read a block of data from the file.
  137. *
  138. * @param buf Byte buffer to receive the data.
  139. * @param siz Maximum length of data to receive.
  140. * @param offset Offset within buffer to place received data.
  141. * @param minSiz Minimum read size, zero will return immediately if there is no data
  142. * @return Actual length of data received.
  143. * @exception java.io.IOException If an I/O error occurs
  144. * @exception SMBException If an SMB level error occurs
  145. */
  146. public final int Read(byte[] buf, int siz, int offset, int minSiz)
  147. throws java.io.IOException, SMBException {
  148. // Read from the pipe
  149. return Read(buf, siz, offset, NoTimeout, minSiz);
  150. }
  151. /**
  152. * Read a block of data from the file.
  153. *
  154. * @param buf Byte buffer to receive the data.
  155. * @param siz Maximum length of data to receive.
  156. * @param offset Offset within buffer to place received data.
  157. * @param tmo Read timeout
  158. * @param minSiz Mimimum read size, zero will return immediately if there is no data
  159. * @return Actual length of data received.
  160. * @exception java.io.IOException If an I/O error occurs
  161. * @exception SMBException If an SMB level error occurs
  162. */
  163. private final int Read(byte[] buf, int siz, int offset, int tmo, int minSiz)
  164. throws java.io.IOException, SMBException {
  165. // Check if the file has been closed
  166. if ( this.isClosed())
  167. return -1;
  168. // Check if there is any data buffered
  169. if ( m_rxlen == 0) {
  170. // Read a packet of data from the remote pipe
  171. if ( ReadData(tmo, minSiz) == false)
  172. return -1;
  173. // Check if there is any buffered data
  174. if ( m_rxlen == 0)
  175. return 0;
  176. }
  177. // Copy data to the users buffer
  178. int retlen = m_rxlen;
  179. if ( retlen > siz)
  180. retlen = siz;
  181. byte[] pktbuf = m_rxpkt.getBuffer();
  182. System.arraycopy(pktbuf, m_rxoffset, buf, offset, retlen);
  183. // Update the buffered data offset/length
  184. m_rxlen -= retlen;
  185. m_rxoffset += retlen;
  186. // Return the amount of data read
  187. return retlen;
  188. }
  189. /**
  190. * Read a packet of data from the remote file.
  191. *
  192. * @param tmo Read timeout, zero for no timeout
  193. * @param minSiz Minimum read size, zero will return imeediately if there is no data
  194. * @return true if a valid data packet has been received, else false
  195. * @exception SMBException If an SMB level error occurs
  196. * @exception IOException If an I/O error occurs
  197. */
  198. private final boolean ReadData(int tmo, int minSiz)
  199. throws SMBException, IOException {
  200. // Check if the file offset requires large file support (64bit offsets)
  201. if ( isNTDialect() == false && m_rxpos > Maximum32BitOffset)
  202. throw new SMBException(SMBStatus.JLANErr, SMBStatus.JLANLargeFilesNotSupported);
  203. // If the pipe is broken then return an error
  204. if ( isPipeBroken())
  205. throw new SMBException(SMBStatus.NTErr, SMBStatus.NTPipeBroken);
  206. // Allocate and initialize a receive packet, if not already allocated
  207. if ( m_rxpkt == null) {
  208. // Allocate a receive packet
  209. m_rxpkt = m_sess.allocatePacket(PacketSize);
  210. // Initialize the packet
  211. m_rxpkt.setUserId(m_sess.getUserId());
  212. m_rxpkt.setTreeId(m_sess.getTreeId());
  213. }
  214. // Read a packet of data from the remote file
  215. m_rxpkt.setCommand(PacketType.ReadAndX);
  216. m_rxpkt.setParameterCount(isNTDialect() ? 12 : 10);
  217. m_rxpkt.setAndXCommand(PacketType.NoChainedCommand);
  218. m_rxpkt.setFlags(m_sess.getDefaultFlags());
  219. m_rxpkt.setFlags2(m_sess.getDefaultFlags2());
  220. m_rxpkt.setProcessId(m_sess.getProcessId());
  221. // Set the file id and read offset
  222. m_rxpkt.setParameter(2, getFileId());
  223. m_rxpkt.setParameterLong(3, (int) (m_rxpos & 0xFFFFFFFF));
  224. // Set the maximum read size
  225. int maxCount = m_rxpkt.getBuffer().length - 64;
  226. m_rxpkt.setParameter(5, maxCount);
  227. // Set the minimum read size
  228. m_rxpkt.setParameter(6, minSiz);
  229. // Read timeout, zero for no timeout
  230. m_rxpkt.setParameterLong(7, tmo);
  231. // Bytes remaining to satisfy request
  232. m_rxpkt.setParameter(9, maxCount);
  233. // Set the top 32bits of the file offset for NT dialect
  234. if ( isNTDialect())
  235. m_rxpkt.setParameterLong(10, (int) ((m_rxpos >> 32) & 0x0FFFFFFFFL));
  236. // No byte data
  237. m_rxpkt.setByteCount(0);
  238. // Exchange the read data SMB packet with the file server
  239. try {
  240. m_rxpkt.ExchangeSMB(m_sess, m_rxpkt, true);
  241. }
  242. catch (SocketTimeoutException ex) {
  243. return false;
  244. }
  245. catch (SMBException ex) {
  246. // Check for a pipe empty status
  247. if ( ex.getErrorClass() == SMBStatus.NTErr && ex.getErrorCode() == SMBStatus.NTPipeEmpty) {
  248. // Indicate success, but no data received so receive length will still be zero
  249. return true;
  250. }
  251. else if ( ex.getErrorClass() == SMBStatus.NTErr
  252. && (ex.getErrorCode() == SMBStatus.NTPipeBroken || ex.getErrorCode() == SMBStatus.NTPipeDisconnected)) {
  253. // Indicate end of file, and set the pipe broken state
  254. setStateFlag(SMBFile.EndOfFile, true);
  255. setStateFlag(PipeBroken, true);
  256. return false;
  257. }
  258. else {
  259. // Rethrow the exception
  260. throw ex;
  261. }
  262. }
  263. // Check if a valid response was received
  264. if ( m_rxpkt.isValidResponse()) {
  265. // Set the received data length and offset within the received data
  266. m_rxlen = m_rxpkt.getParameter(5);
  267. m_rxoffset = m_rxpkt.getParameter(6) + RFCNetBIOSProtocol.HEADER_LEN;
  268. // Update the current receive file position
  269. m_rxpos += m_rxlen;
  270. // Check if we have reached the end of file, indicated by a zero length
  271. // read.
  272. // if (m_rxlen == 0)
  273. // setStateFlag(SMBFile.EndOfFile, true);
  274. return true;
  275. }
  276. // Return a failure status
  277. return false;
  278. }
  279. /**
  280. * Write a block of data to the file.
  281. *
  282. * @param buf Byte buffer containing data to be written.
  283. * @param siz Length of data to be written.
  284. * @param offset Offset within buffer to start writing data from.
  285. * @return Actual length of data written.
  286. * @exception java.io.IOException If an I/O error occurs
  287. * @exception SMBException If an SMB level error occurs
  288. */
  289. public final int Write(byte[] buf, int siz, int offset)
  290. throws java.io.IOException, SMBException {
  291. // Check if the file has been closed
  292. if ( this.isClosed())
  293. return 0;
  294. // Allocate and initialize a transmit packet, if not already allocated
  295. if ( m_txpkt == null) {
  296. // Allocate a transmit packet
  297. m_txpkt = m_sess.allocatePacket(PacketSize);
  298. // Initialize the packet
  299. m_txpkt.setUserId(m_sess.getUserId());
  300. m_txpkt.setTreeId(m_sess.getTreeId());
  301. m_txpkt.setProcessId(m_sess.getProcessId());
  302. // Set the write SMB parameter count now, so that we can calculate the
  303. // offset of the byte buffer within the packet.
  304. m_txpkt.setParameterCount(isNTDialect() ? 14 : 12);
  305. // Clear the write packet length and initialize the write packet offset.
  306. m_txlen = 0;
  307. m_txoffset = WriteDataOffset;
  308. if ( isNTDialect())
  309. m_txoffset += 4;
  310. }
  311. // Move the data to the write packet and send write requests until the
  312. // user write has been done.
  313. int txlen = 0;
  314. while (txlen < siz) {
  315. // Determine if the current write request can be buffered in full
  316. byte[] pktbuf = m_txpkt.getBuffer();
  317. int len = pktbuf.length - m_txoffset;
  318. if ( len > (siz - txlen))
  319. len = siz - txlen;
  320. // Move the user data to the write packet
  321. System.arraycopy(buf, offset, pktbuf, m_txoffset, len);
  322. m_txoffset += len;
  323. offset += len;
  324. // Update the written data length
  325. txlen += len;
  326. m_txlen += len;
  327. // Write the data immediately for pipes
  328. WriteData();
  329. } // end while writing
  330. // Return the length of the data that was written
  331. return txlen;
  332. }
  333. /**
  334. * Write a packet of data to the remote file.
  335. *
  336. * @return true if the write was successful, else false
  337. * @exception SMBException If an SMB level error occurs
  338. * @exception IOException If an I/O error occurs
  339. */
  340. private final boolean WriteData()
  341. throws SMBException, IOException {
  342. // Check if the file offset requires large file support (64bit offsets)
  343. if ( isNTDialect() == false && m_txpos > Maximum32BitOffset)
  344. throw new SMBException(SMBStatus.JLANErr, SMBStatus.JLANLargeFilesNotSupported);
  345. // Write a packet of data to the remote file
  346. m_txpkt.setCommand(PacketType.WriteAndX);
  347. m_txpkt.setAndXCommand(PacketType.NoChainedCommand);
  348. m_txpkt.setFlags(m_sess.getDefaultFlags());
  349. m_txpkt.setFlags2(m_sess.getDefaultFlags2());
  350. m_txpkt.setParameterCount(isNTDialect() ? 14 : 12);
  351. // Set the file id and file offset
  352. m_txpkt.setParameter(2, getFileId());
  353. m_txpkt.setParameterLong(3, (int) (m_txpos & 0xFFFFFFFF));
  354. m_txpkt.setParameterLong(5, 0);
  355. // Set the write mode
  356. m_txpkt.setParameter(7, 0x0008); // pipe message start
  357. // Set the bytes remaining for request and reserved area
  358. m_txpkt.setParameter(8, m_txlen);
  359. m_txpkt.setParameter(9, 0);
  360. // Set the data length and offset from start of packet
  361. m_txpkt.setParameter(10, m_txlen);
  362. int offset = WriteDataOffset - RFCNetBIOSProtocol.HEADER_LEN;
  363. if ( isNTDialect())
  364. offset += 4;
  365. m_txpkt.setParameter(11, offset);
  366. // Add the top 32bits of the file offset, for NT dialect. Set the byte count, includes any
  367. // padding
  368. // bytes
  369. if ( isNTDialect()) {
  370. // Set the top 32bits of the file offset
  371. m_txpkt.setParameterLong(12, (int) ((m_txpos >> 32) & 0xFFFFFFFFL));
  372. }
  373. // Set the byte count, includes any padding bytes
  374. m_txpkt.setByteCount(m_txlen + WriteDataPadding);
  375. // Exchange the write data SMB packet with the file server
  376. m_txpkt.ExchangeSMB(m_sess, m_txpkt, false);
  377. // Check if a valid response was received
  378. if ( m_txpkt.isValidResponse()) {
  379. // Set the write data length
  380. int txlen = m_txpkt.getParameter(2);
  381. // Update the current write file position
  382. m_txpos += txlen;
  383. // Reset the write packet and write length
  384. m_txlen = 0;
  385. m_txoffset = WriteDataOffset;
  386. if ( isNTDialect())
  387. m_txoffset += 4;
  388. return true;
  389. }
  390. else {
  391. // Reset the write packet and write length
  392. m_txlen = 0;
  393. m_txoffset = WriteDataOffset;
  394. if ( isNTDialect())
  395. m_txoffset += 4;
  396. // Throw an exception
  397. m_txpkt.checkForError();
  398. }
  399. // Return a failure status
  400. return false;
  401. }
  402. /**
  403. * Seek to the specified point in the file. The seek may be relative to the start of file,
  404. * current file position or end of file.
  405. *
  406. * @param pos Relative offset
  407. * @param typ Seek type (@see org.alfresco.jlan.smb.SeekType)
  408. * @return New file offset from start of file
  409. * @exception IOException
  410. * @exception SMBException If an SMB level error occurs
  411. */
  412. public long Seek(long pos, int typ)
  413. throws IOException, SMBException {
  414. // Check if the file has been closed
  415. if ( this.isClosed())
  416. throw new IOException("Seek on closed file");
  417. // Flush any buffered data
  418. Flush();
  419. // Reset the read/write offsets to the new file position
  420. switch (typ) {
  421. // Seek relative to the start of file
  422. case SeekType.StartOfFile:
  423. m_txpos = m_rxpos = pos;
  424. break;
  425. // Seek realtive to the current file position
  426. case SeekType.CurrentPos:
  427. m_txpos = m_rxpos + pos;
  428. m_rxpos = m_txpos;
  429. break;
  430. // Seek relative to end of file
  431. case SeekType.EndOfFile:
  432. m_txpos = m_rxpos = getFileSize() + pos;
  433. break;
  434. }
  435. // Indicate that there is no buffered data
  436. m_txlen = 0;
  437. m_rxlen = 0;
  438. // Return the new file offset
  439. return m_rxpos;
  440. }
  441. /**
  442. * Lock a range of bytes within the file
  443. *
  444. * @param offset Offset within the file to start lock
  445. * @param len Number of bytes to lock
  446. * @exception IOException
  447. * @exception SMBException If an SMB level error occurs
  448. */
  449. public void Lock(long offset, long len)
  450. throws IOException, SMBException {
  451. // Check if the file offset requires large file support (64bit offsets)
  452. if ( isNTDialect() == false && offset > Maximum32BitOffset)
  453. throw new SMBException(SMBStatus.JLANErr, SMBStatus.JLANLargeFilesNotSupported);
  454. // Create the lock request packet
  455. SMBPacket pkt = new SMBPacket();
  456. pkt.setUserId(m_sess.getUserId());
  457. pkt.setTreeId(m_sess.getTreeId());
  458. pkt.setCommand(PacketType.LockingAndX);
  459. pkt.setProcessId(m_sess.getProcessId());
  460. // Set the parameters
  461. pkt.setParameterCount(8);
  462. pkt.setAndXCommand(PacketType.NoChainedCommand);
  463. pkt.setParameter(2, m_FID);
  464. pkt.setParameter(3, m_sess.supportsLargeFiles() ? LockingAndX.LargeFiles : 0);
  465. pkt.setParameterLong(4, 0); // timeout, for unlock
  466. pkt.setParameter(6, 0); // number of unlock structures
  467. pkt.setParameter(7, 1); // number of lock structures
  468. // Pack the lock structure
  469. pkt.resetBytePointer();
  470. if ( m_sess.supportsLargeFiles()) {
  471. // Pack a large file (64bit) format structure
  472. pkt.packWord(m_sess.getProcessId());
  473. pkt.packWord(0);
  474. pkt.packInt((int) ((offset >> 32) & 0xFFFFFFFFL));
  475. pkt.packInt((int) (offset & 0xFFFFFFFFL));
  476. pkt.packInt((int) ((len >> 32) & 0xFFFFFFFFL));
  477. pkt.packInt((int) (len & 0xFFFFFFFFL));
  478. }
  479. else {
  480. // Pack a normal (32bit) format structure
  481. pkt.packWord(m_sess.getProcessId());
  482. pkt.packInt((int) (offset & 0xFFFFFFFFL));
  483. pkt.packInt((int) (len & 0xFFFFFFFFL));
  484. }
  485. // Set the byte count
  486. pkt.setByteCount();
  487. // Send the lock request
  488. pkt.ExchangeSMB(m_sess, pkt, true);
  489. }
  490. /**
  491. * Unlock a range of bytes within the file
  492. *
  493. * @param offset Offset within the file to unlock
  494. * @param len Number of bytes to unlock
  495. * @exception IOException
  496. * @exception SMBException If an SMB level error occurs
  497. */
  498. public void Unlock(long offset, long len)
  499. throws IOException, SMBException {
  500. // Check if the file offset requires large file support (64bit offsets)
  501. if ( isNTDialect() == false && offset > Maximum32BitOffset)
  502. throw new SMBException(SMBStatus.JLANErr, SMBStatus.JLANLargeFilesNotSupported);
  503. // Create the unlock request packet
  504. SMBPacket pkt = new SMBPacket();
  505. pkt.setUserId(m_sess.getUserId());
  506. pkt.setTreeId(m_sess.getTreeId());
  507. pkt.setCommand(PacketType.LockingAndX);
  508. pkt.setProcessId(m_sess.getProcessId());
  509. // Set the parameters
  510. pkt.setParameterCount(8);
  511. pkt.setAndXCommand(PacketType.NoChainedCommand);
  512. pkt.setParameter(2, m_FID);
  513. pkt.setParameter(3, m_sess.supportsLargeFiles() ? LockingAndX.LargeFiles : 0);
  514. pkt.setParameterLong(4, 0); // timeout, for unlock
  515. pkt.setParameter(6, 1); // number of unlock structures
  516. pkt.setParameter(7, 0); // number of lock structures
  517. // Pack the unlock structure
  518. pkt.resetBytePointer();
  519. if ( m_sess.supportsLargeFiles()) {
  520. // Pack a large file (64bit) format structure
  521. pkt.packWord(m_sess.getProcessId());
  522. pkt.packWord(0);
  523. pkt.packInt((int) ((offset >> 32) & 0xFFFFFFFFL));
  524. pkt.packInt((int) (offset & 0xFFFFFFFFL));
  525. pkt.packInt((int) ((len >> 32) & 0xFFFFFFFFL));
  526. pkt.packInt((int) (len & 0xFFFFFFFFL));
  527. }
  528. else {
  529. // Pack a normal (32bit) format structure
  530. pkt.packWord(m_sess.getProcessId());
  531. pkt.packInt((int) (offset & 0xFFFFFFFFL));
  532. pkt.packInt((int) (len & 0xFFFFFFFFL));
  533. }
  534. // Set the byte count
  535. pkt.setByteCount();
  536. // Send the unlock request
  537. pkt.ExchangeSMB(m_sess, pkt, true);
  538. }
  539. /**
  540. * Check if NT dialect SMBs should be used
  541. *
  542. * @return boolean
  543. */
  544. protected final boolean isNTDialect() {
  545. return m_NTdialect;
  546. }
  547. /**
  548. * Check if the pipe is broken
  549. *
  550. * @return boolean
  551. */
  552. public final boolean isPipeBroken() {
  553. return hasStateFlag(PipeBroken);
  554. }
  555. }