001: /* jcifs smb client library in Java
002: * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package com.knowgate.jcifs.smb;
020:
021: import java.net.URL;
022: import java.io.OutputStream;
023: import java.io.IOException;
024: import java.net.UnknownHostException;
025: import java.net.MalformedURLException;
026:
027: import com.knowgate.debug.*;
028:
029: /**
030: * This <code>OutputStream</code> can write bytes to a file on an SMB file server.
031: */
032:
033: public class SmbFileOutputStream extends OutputStream {
034:
035: private SmbFile file;
036: private boolean append, useNTSmbs;
037: private int openFlags, writeSize;
038: private long fp;
039: private byte[] tmp = new byte[1];
040: private SmbComWriteAndX reqx;
041: private SmbComWriteAndXResponse rspx;
042: private SmbComWrite req;
043: private SmbComWriteResponse rsp;
044:
045: /**
046: * Creates an {@link java.io.OutputStream} for writing to a file
047: * on an SMB server addressed by the URL parameter. See {@link
048: * jcifs.smb.SmbFile} for a detailed description and examples of
049: * the smb URL syntax.
050: *
051: * @param url An smb URL string representing the file to write to
052: * @return A new <code>OutputStream</code> for the specified file
053: */
054:
055: public SmbFileOutputStream(String url) throws SmbException,
056: MalformedURLException, UnknownHostException {
057: this (url, false);
058: }
059:
060: /**
061: * Creates an {@link java.io.OutputStream} for writing bytes to a file on
062: * an SMB server represented by the {@link jcifs.smb.SmbFile} parameter. See
063: * {@link jcifs.smb.SmbFile} for a detailed description and examples of
064: * the smb URL syntax.
065: *
066: * @param url An <code>SmbFile</code> specifying the file to write to
067: * @return A new <code>OutputStream</code> for the specified <code>SmbFile</code>
068: */
069:
070: public SmbFileOutputStream(SmbFile file) throws SmbException,
071: MalformedURLException, UnknownHostException {
072: this (file, false);
073: }
074:
075: /**
076: * Creates an {@link java.io.OutputStream} for writing bytes to a file on an
077: * SMB server addressed by the URL parameter. See {@link jcifs.smb.SmbFile}
078: * for a detailed description and examples of the smb URL syntax. If the
079: * second argument is <code>true</code>, then bytes will be written to the
080: * end of the file rather than the beginning.
081: *
082: * @param url An smb URL string representing the file to write to
083: * @return A new <code>OutputStream</code> for the specified <code>url</code>
084: */
085:
086: public SmbFileOutputStream(String url, boolean append)
087: throws SmbException, MalformedURLException,
088: UnknownHostException {
089: this (new SmbFile(url), append);
090: }
091:
092: /**
093: * Creates an {@link java.io.OutputStream} for writing bytes to a file
094: * on an SMB server addressed by the <code>SmbFile</code> parameter. See
095: * {@link jcifs.smb.SmbFile} for a detailed description and examples of
096: * the smb URL syntax. If the second argument is <code>true</code>, then
097: * bytes will be written to the end of the file rather than the beginning.
098: *
099: * @param url An <code>SmbFile</code> representing the file to write to
100: * @return A new <code>OutputStream</code> for the specified <code>SmbFile</code>
101: */
102:
103: public SmbFileOutputStream(SmbFile file, boolean append)
104: throws SmbException, MalformedURLException,
105: UnknownHostException {
106: this (file, append, append ? SmbFile.O_CREAT | SmbFile.O_WRONLY
107: | SmbFile.O_APPEND : SmbFile.O_CREAT | SmbFile.O_WRONLY
108: | SmbFile.O_TRUNC);
109: }
110:
111: /**
112: * Creates an {@link java.io.OutputStream} for writing bytes to a file
113: * on an SMB server addressed by the <code>SmbFile</code> parameter. See
114: * {@link jcifs.smb.SmbFile} for a detailed description and examples of
115: * the smb URL syntax.
116: <p>
117: The second parameter specifies how the file should be shared. If
118: <code>SmbFile.FILE_NO_SHARE</code> is specified the client will
119: have exclusive access to the file. An additional open command
120: from jCIFS or another application will fail with the "file is being
121: accessed by another process" error. The <code>FILE_SHARE_READ</code>,
122: <code>FILE_SHARE_WRITE</code>, and <code>FILE_SHARE_DELETE</code> may be
123: combined with the bitwise OR '|' to specify that other peocesses may read,
124: write, and/or delete the file while the jCIFS user has the file open.
125: *
126: * @param url An <code>SmbFile</code> representing the file to write to
127: * @return A new <code>OutputStream</code> for the specified <code>SmbFile</code>
128: */
129:
130: public SmbFileOutputStream(String url, int shareAccess)
131: throws SmbException, MalformedURLException,
132: UnknownHostException {
133: this (new SmbFile(url, "", null, shareAccess), false);
134: }
135:
136: SmbFileOutputStream(SmbFile file, boolean append, int openFlags)
137: throws SmbException, MalformedURLException,
138: UnknownHostException {
139: this .file = file;
140: this .append = append;
141: this .openFlags = openFlags;
142: if (append) {
143: try {
144: fp = file.length();
145: } catch (SmbException se) {
146: fp = 0L;
147: }
148: }
149: if (file instanceof SmbNamedPipe
150: && file.unc.startsWith("\\pipe\\")) {
151: file.unc = file.unc.substring(5);
152: file.sendTransaction(new TransWaitNamedPipe("\\pipe"
153: + file.unc), new TransWaitNamedPipeResponse());
154: }
155: file.open(openFlags, SmbFile.ATTR_NORMAL, 0);
156: writeSize = file.tree.session.transport.snd_buf_size - 70;
157:
158: useNTSmbs = file.tree.session.transport
159: .hasCapability(ServerMessageBlock.CAP_NT_SMBS);
160: if (useNTSmbs) {
161: reqx = new SmbComWriteAndX();
162: rspx = new SmbComWriteAndXResponse();
163: } else {
164: req = new SmbComWrite();
165: rsp = new SmbComWriteResponse();
166: }
167: }
168:
169: /**
170: * Closes this output stream and releases any system resources associated
171: * with it.
172: *
173: * @throws IOException if a network error occurs
174: */
175:
176: public void close() throws IOException {
177: file.close();
178: }
179:
180: /**
181: * Writes the specified byte to this file output stream.
182: *
183: * @throws IOException if a network error occurs
184: */
185:
186: public void write(int b) throws IOException {
187: tmp[0] = (byte) b;
188: write(tmp, 0, 1);
189: }
190:
191: /**
192: * Writes b.length bytes from the specified byte array to this
193: * file output stream.
194: *
195: * @throws IOException if a network error occurs
196: */
197:
198: public void write(byte[] b) throws IOException {
199: write(b, 0, b.length);
200: }
201:
202: /**
203: * Writes len bytes from the specified byte array starting at
204: * offset off to this file output stream.
205: *
206: * @param b The array
207: * @throws IOException if a network error occurs
208: */
209:
210: public void write(byte[] b, int off, int len) throws IOException {
211: if (len <= 0) {
212: return;
213: }
214:
215: // ensure file is open
216: if (file.isOpen() == false) {
217: if (file instanceof SmbNamedPipe) {
218: file.sendTransaction(new TransWaitNamedPipe("\\pipe"
219: + file.unc), new TransWaitNamedPipeResponse());
220: }
221: file.open(openFlags, SmbFile.ATTR_NORMAL, 0);
222: if (append) {
223: fp = file.length();
224: }
225: }
226:
227: if (DebugFile.trace)
228: DebugFile.writeln("write: fid=" + file.fid + ",off=" + off
229: + ",len=" + len);
230:
231: int w;
232: do {
233: w = len > writeSize ? writeSize : len;
234: if (useNTSmbs) {
235: reqx.setParam(file.fid, fp, len - w, b, off, w);
236: file.send(reqx, rspx);
237: fp += rspx.count;
238: len -= rspx.count;
239: off += rspx.count;
240: } else {
241: req.setParam(file.fid, fp, len - w, b, off, w);
242: fp += rsp.count;
243: len -= rsp.count;
244: off += rsp.count;
245: file.send(req, rsp);
246: }
247: } while (len > 0);
248: }
249: }
|