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 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: import jcifs.util.LogStream;
027:
028: /**
029: * This <code>OutputStream</code> can write bytes to a file on an SMB file server.
030: */
031:
032: public class SmbFileOutputStream extends OutputStream {
033:
034: private SmbFile file;
035: private boolean append, useNTSmbs;
036: private int openFlags, writeSize;
037: private long fp;
038: private byte[] tmp = new byte[1];
039: private SmbComWriteAndX reqx;
040: private SmbComWriteAndXResponse rspx;
041: private SmbComWrite req;
042: private SmbComWriteResponse rsp;
043:
044: /**
045: * Creates an {@link java.io.OutputStream} for writing to a file
046: * on an SMB server addressed by the URL parameter. See {@link
047: * jcifs.smb.SmbFile} for a detailed description and examples of
048: * the smb URL syntax.
049: *
050: * @param url An smb URL string representing the file to write to
051: */
052:
053: public SmbFileOutputStream(String url) throws SmbException,
054: MalformedURLException, UnknownHostException {
055: this (url, false);
056: }
057:
058: /**
059: * Creates an {@link java.io.OutputStream} for writing bytes to a file on
060: * an SMB server represented by the {@link jcifs.smb.SmbFile} parameter. See
061: * {@link jcifs.smb.SmbFile} for a detailed description and examples of
062: * the smb URL syntax.
063: *
064: * @param file An <code>SmbFile</code> specifying the file to write to
065: */
066:
067: public SmbFileOutputStream(SmbFile file) throws SmbException,
068: MalformedURLException, UnknownHostException {
069: this (file, false);
070: }
071:
072: /**
073: * Creates an {@link java.io.OutputStream} for writing bytes to a file on an
074: * SMB server addressed by the URL parameter. See {@link jcifs.smb.SmbFile}
075: * for a detailed description and examples of the smb URL syntax. If the
076: * second argument is <code>true</code>, then bytes will be written to the
077: * end of the file rather than the beginning.
078: *
079: * @param url An smb URL string representing the file to write to
080: * @param append Append to the end of file
081: */
082:
083: public SmbFileOutputStream(String url, boolean append)
084: throws SmbException, MalformedURLException,
085: UnknownHostException {
086: this (new SmbFile(url), append);
087: }
088:
089: /**
090: * Creates an {@link java.io.OutputStream} for writing bytes to a file
091: * on an SMB server addressed by the <code>SmbFile</code> parameter. See
092: * {@link jcifs.smb.SmbFile} for a detailed description and examples of
093: * the smb URL syntax. If the second argument is <code>true</code>, then
094: * bytes will be written to the end of the file rather than the beginning.
095: *
096: * @param file An <code>SmbFile</code> representing the file to write to
097: * @param append Append to the end of file
098: */
099:
100: public SmbFileOutputStream(SmbFile file, boolean append)
101: throws SmbException, MalformedURLException,
102: UnknownHostException {
103: this (file, append, append ? SmbFile.O_CREAT | SmbFile.O_WRONLY
104: | SmbFile.O_APPEND : SmbFile.O_CREAT | SmbFile.O_WRONLY
105: | SmbFile.O_TRUNC);
106: }
107:
108: /**
109: * Creates an {@link java.io.OutputStream} for writing bytes to a file
110: * on an SMB server addressed by the <code>SmbFile</code> parameter. See
111: * {@link jcifs.smb.SmbFile} for a detailed description and examples of
112: * the smb URL syntax.
113: <p>
114: The second parameter specifies how the file should be shared. If
115: <code>SmbFile.FILE_NO_SHARE</code> is specified the client will
116: have exclusive access to the file. An additional open command
117: from jCIFS or another application will fail with the "file is being
118: accessed by another process" error. The <code>FILE_SHARE_READ</code>,
119: <code>FILE_SHARE_WRITE</code>, and <code>FILE_SHARE_DELETE</code> may be
120: combined with the bitwise OR '|' to specify that other peocesses may read,
121: write, and/or delete the file while the jCIFS user has the file open.
122: *
123: * @param url An smb URL representing the file to write to
124: * @param shareAccess File sharing flag: <code>SmbFile.FILE_NOSHARE</code> or any combination of <code>SmbFile.FILE_READ</code>, <code>SmbFile.FILE_WRITE</code>, and <code>SmbFile.FILE_DELETE</code>
125: */
126:
127: public SmbFileOutputStream(String url, int shareAccess)
128: throws SmbException, MalformedURLException,
129: UnknownHostException {
130: this (new SmbFile(url, "", null, shareAccess), false);
131: }
132:
133: SmbFileOutputStream(SmbFile file, boolean append, int openFlags)
134: throws SmbException, MalformedURLException,
135: UnknownHostException {
136: this .file = file;
137: this .append = append;
138: this .openFlags = openFlags;
139: if (append) {
140: try {
141: fp = file.length();
142: } catch (SmbException se) {
143: fp = 0L;
144: }
145: }
146: if (file instanceof SmbNamedPipe
147: && file.unc.startsWith("\\pipe\\")) {
148: file.unc = file.unc.substring(5);
149: file.sendTransaction(new TransWaitNamedPipe("\\pipe"
150: + file.unc), new TransWaitNamedPipeResponse());
151: }
152: file.open(openFlags, SmbFile.ATTR_NORMAL, 0);
153: this .openFlags &= ~(SmbFile.O_CREAT | SmbFile.O_TRUNC); /* in case close and reopen */
154: writeSize = file.tree.session.transport.snd_buf_size - 70;
155:
156: useNTSmbs = file.tree.session.transport
157: .hasCapability(ServerMessageBlock.CAP_NT_SMBS);
158: if (useNTSmbs) {
159: reqx = new SmbComWriteAndX();
160: rspx = new SmbComWriteAndXResponse();
161: } else {
162: req = new SmbComWrite();
163: rsp = new SmbComWriteResponse();
164: }
165: }
166:
167: /**
168: * Closes this output stream and releases any system resources associated
169: * with it.
170: *
171: * @throws IOException if a network error occurs
172: */
173:
174: public void close() throws IOException {
175: file.close();
176: tmp = null;
177: }
178:
179: /**
180: * Writes the specified byte to this file output stream.
181: *
182: * @throws IOException if a network error occurs
183: */
184:
185: public void write(int b) throws IOException {
186: tmp[0] = (byte) b;
187: write(tmp, 0, 1);
188: }
189:
190: /**
191: * Writes b.length bytes from the specified byte array to this
192: * file output stream.
193: *
194: * @throws IOException if a network error occurs
195: */
196:
197: public void write(byte[] b) throws IOException {
198: write(b, 0, b.length);
199: }
200:
201: /**
202: * Writes len bytes from the specified byte array starting at
203: * offset off to this file output stream.
204: *
205: * @param b The array
206: * @throws IOException if a network error occurs
207: */
208:
209: public void write(byte[] b, int off, int len) throws IOException {
210: if (len <= 0) {
211: return;
212: }
213:
214: if (tmp == null) {
215: throw new IOException("Bad file descriptor");
216: }
217: // ensure file is open
218: if (file.isOpen() == false) {
219: if (file instanceof SmbNamedPipe) {
220: file.sendTransaction(new TransWaitNamedPipe("\\pipe"
221: + file.unc), new TransWaitNamedPipeResponse());
222: }
223: file.open(openFlags, SmbFile.ATTR_NORMAL, 0);
224: if (append) {
225: fp = file.length();
226: }
227: }
228:
229: if (file.log.level > 2)
230: file.log.println("write: fid=" + file.fid + ",off=" + off
231: + ",len=" + len);
232:
233: int w;
234: do {
235: w = len > writeSize ? writeSize : len;
236: if (useNTSmbs) {
237: reqx.setParam(file.fid, fp, len - w, b, off, w);
238: file.send(reqx, rspx);
239: fp += rspx.count;
240: len -= rspx.count;
241: off += rspx.count;
242: } else {
243: req.setParam(file.fid, fp, len - w, b, off, w);
244: fp += rsp.count;
245: len -= rsp.count;
246: off += rsp.count;
247: file.send(req, rsp);
248: }
249: } while (len > 0);
250: }
251: }
|