jcifs.smb.SmbTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcifs-krb5-jdk7 Show documentation
Show all versions of jcifs-krb5-jdk7 Show documentation
JCIFS is an Open Source client library that implements the CIFS/SMB networking protocol in 100% Java
/* jcifs smb client library in Java
* Copyright (C) 2000 "Michael B. Allen"
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jcifs.smb;
import java.io.IOException;
import java.net.UnknownHostException;
import jcifs.UniAddress;
import jcifs.netbios.NbtAddress;
import jcifs.Config;
class SmbTree {
private static int tree_conn_counter;
/* 0 - not connected
* 1 - connecting
* 2 - connected
* 3 - disconnecting
*/
int connectionState;
int tid;
String share;
String service = "?????";
String service0;
SmbSession session;
boolean inDfs, inDomainDfs;
int tree_num; // used by SmbFile.isOpen
SmbTree( SmbSession session, String share, String service ) {
this.session = session;
this.share = share.toUpperCase();
if( service != null && service.startsWith( "??" ) == false ) {
this.service = service;
}
this.service0 = this.service;
this.connectionState = 0;
}
boolean matches( String share, String service ) {
return this.share.equalsIgnoreCase( share ) &&
( service == null || service.startsWith( "??" ) ||
this.service.equalsIgnoreCase( service ));
}
public boolean equals(Object obj) {
if (obj instanceof SmbTree) {
SmbTree tree = (SmbTree)obj;
return matches(tree.share, tree.service);
}
return false;
}
void send( ServerMessageBlock request,
ServerMessageBlock response ) throws SmbException {
synchronized (session.transport()) {
if( response != null ) {
response.received = false;
}
treeConnect( request, response );
if( request == null || (response != null && response.received )) {
return;
}
if( service.equals( "A:" ) == false ) {
switch( request.command ) {
case ServerMessageBlock.SMB_COM_OPEN_ANDX:
case ServerMessageBlock.SMB_COM_NT_CREATE_ANDX:
case ServerMessageBlock.SMB_COM_READ_ANDX:
case ServerMessageBlock.SMB_COM_WRITE_ANDX:
case ServerMessageBlock.SMB_COM_CLOSE:
case ServerMessageBlock.SMB_COM_TREE_DISCONNECT:
break;
case ServerMessageBlock.SMB_COM_TRANSACTION:
case ServerMessageBlock.SMB_COM_TRANSACTION2:
switch( ((SmbComTransaction)request).subCommand & 0xFF ) {
case SmbComTransaction.NET_SHARE_ENUM:
case SmbComTransaction.NET_SERVER_ENUM2:
case SmbComTransaction.NET_SERVER_ENUM3:
case SmbComTransaction.TRANS_PEEK_NAMED_PIPE:
case SmbComTransaction.TRANS_WAIT_NAMED_PIPE:
case SmbComTransaction.TRANS_CALL_NAMED_PIPE:
case SmbComTransaction.TRANS_TRANSACT_NAMED_PIPE:
case SmbComTransaction.TRANS2_GET_DFS_REFERRAL:
break;
default:
throw new SmbException( "Invalid operation for " + service + " service" );
}
break;
default:
throw new SmbException( "Invalid operation for " + service + " service" + request );
}
}
request.tid = tid;
if( inDfs && !service.equals("IPC") && request.path != null && request.path.length() > 0 ) {
/* When DFS is in action all request paths are
* full UNC paths minus the first backslash like
* \server\share\path\to\file
* as opposed to normally
* \path\to\file
*/
request.flags2 = ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
request.path = '\\' + session.transport().tconHostName + '\\' + share + request.path;
}
try {
session.send( request, response );
} catch( SmbException se ) {
if (se.getNtStatus() == se.NT_STATUS_NETWORK_NAME_DELETED) {
/* Someone removed the share while we were
* connected. Bastards! Disconnect this tree
* so that it reconnects cleanly should the share
* reappear in this client's lifetime.
*/
treeDisconnect( true );
}
throw se;
}
}
}
void treeConnect( ServerMessageBlock andx,
ServerMessageBlock andxResponse ) throws SmbException {
synchronized (session.transport()) {
String unc;
while (connectionState != 0) {
if (connectionState == 2 || connectionState == 3) // connected or disconnecting
return;
try {
session.transport.wait();
} catch (InterruptedException ie) {
throw new SmbException(ie.getMessage(), ie);
}
}
connectionState = 1; // trying ...
try {
/* The hostname to use in the path is only known for
* sure if the NetBIOS session has been successfully
* established.
*/
session.transport.connect();
unc = "\\\\" + session.transport.tconHostName + '\\' + share;
/* IBM iSeries doesn't like specifying a service. Always reset
* the service to whatever was determined in the constructor.
*/
service = service0;
/*
* Tree Connect And X Request / Response
*/
if( session.transport.log.level >= 4 )
session.transport.log.println( "treeConnect: unc=" + unc + ",service=" + service );
SmbComTreeConnectAndXResponse response =
new SmbComTreeConnectAndXResponse( andxResponse );
SmbComTreeConnectAndX request =
new SmbComTreeConnectAndX( session, unc, service, andx );
session.send( request, response );
tid = response.tid;
service = response.service;
inDfs = response.shareIsInDfs;
tree_num = tree_conn_counter++;
connectionState = 2; // connected
} catch (SmbException se) {
treeDisconnect(true);
connectionState = 0;
throw se;
}
}
}
void treeDisconnect( boolean inError ) {
synchronized (session.transport()) {
if (connectionState != 2) // not-connected
return;
connectionState = 3; // disconnecting
if (!inError && tid != 0) {
try {
send( new SmbComTreeDisconnect(), null );
} catch( SmbException se ) {
if (session.transport.log.level > 1) {
se.printStackTrace( session.transport.log );
}
}
}
inDfs = false;
inDomainDfs = false;
connectionState = 0;
session.transport.notifyAll();
}
}
public String toString() {
return "SmbTree[share=" + share +
",service=" + service +
",tid=" + tid +
",inDfs=" + inDfs +
",inDomainDfs=" + inDomainDfs +
",connectionState=" + connectionState + "]";
}
}