/// <summary> /// Convenience method, so that we don't open a new connection when using this /// method from within another method. /// </summary> /// <remarks> /// Convenience method, so that we don't open a new connection when using this /// method from within another method. Otherwise every API invocation incurs /// the overhead of opening/closing a TCP connection. /// </remarks> /// <exception cref="System.IO.IOException"/> private bool Mkdirs(FTPClient client, Path file, FsPermission permission) { bool created = true; Path workDir = new Path(client.PrintWorkingDirectory()); Path absolute = MakeAbsolute(workDir, file); string pathName = absolute.GetName(); if (!Exists(client, absolute)) { Path parent = absolute.GetParent(); created = (parent == null || Mkdirs(client, parent, FsPermission.GetDirDefault()) ); if (created) { string parentDir = parent.ToUri().GetPath(); client.ChangeWorkingDirectory(parentDir); created = created && client.MakeDirectory(pathName); } } else { if (IsFile(client, absolute)) { throw new ParentNotDirectoryException(string.Format("Can't make directory for path %s since it is a file." , absolute)); } } return(created); }
/// <summary> /// A stream obtained via this call must be closed before using other APIs of /// this class or else the invocation will block. /// </summary> /// <exception cref="System.IO.IOException"/> public override FSDataOutputStream Create(Path file, FsPermission permission, bool overwrite, int bufferSize, short replication, long blockSize, Progressable progress ) { FTPClient client = Connect(); Path workDir = new Path(client.PrintWorkingDirectory()); Path absolute = MakeAbsolute(workDir, file); FileStatus status; try { status = GetFileStatus(client, file); } catch (FileNotFoundException) { status = null; } if (status != null) { if (overwrite && !status.IsDirectory()) { Delete(client, file, false); } else { Disconnect(client); throw new FileAlreadyExistsException("File already exists: " + file); } } Path parent = absolute.GetParent(); if (parent == null || !Mkdirs(client, parent, FsPermission.GetDirDefault())) { parent = (parent == null) ? new Path("/") : parent; Disconnect(client); throw new IOException("create(): Mkdirs failed to create: " + parent); } client.Allocate(bufferSize); // Change to parent directory on the server. Only then can we write to the // file on the server by opening up an OutputStream. As a side effect the // working directory on the server is changed to the parent directory of the // file. The FTP client connection is closed when close() is called on the // FSDataOutputStream. client.ChangeWorkingDirectory(parent.ToUri().GetPath()); FSDataOutputStream fos = new _FSDataOutputStream_263(this, client, client.StoreFileStream (file.GetName()), statistics); if (!FTPReply.IsPositivePreliminary(client.GetReplyCode())) { // The ftpClient is an inconsistent state. Must close the stream // which in turn will logout and disconnect from FTP server fos.Close(); throw new IOException("Unable to create file: " + file + ", Aborting"); } return(fos); }
/// <summary> /// Convenience method, so that we don't open a new connection when using this /// method from within another method. /// </summary> /// <remarks> /// Convenience method, so that we don't open a new connection when using this /// method from within another method. Otherwise every API invocation incurs /// the overhead of opening/closing a TCP connection. /// </remarks> /// <param name="client"/> /// <param name="src"/> /// <param name="dst"/> /// <returns/> /// <exception cref="System.IO.IOException"/> private bool Rename(FTPClient client, Path src, Path dst) { Path workDir = new Path(client.PrintWorkingDirectory()); Path absoluteSrc = MakeAbsolute(workDir, src); Path absoluteDst = MakeAbsolute(workDir, dst); if (!Exists(client, absoluteSrc)) { throw new FileNotFoundException("Source path " + src + " does not exist"); } if (IsDirectory(absoluteDst)) { // destination is a directory: rename goes underneath it with the // source name absoluteDst = new Path(absoluteDst, absoluteSrc.GetName()); } if (Exists(client, absoluteDst)) { throw new FileAlreadyExistsException("Destination path " + dst + " already exists" ); } string parentSrc = absoluteSrc.GetParent().ToUri().ToString(); string parentDst = absoluteDst.GetParent().ToUri().ToString(); if (IsParentOf(absoluteSrc, absoluteDst)) { throw new IOException("Cannot rename " + absoluteSrc + " under itself" + " : " + absoluteDst); } if (!parentSrc.Equals(parentDst)) { throw new IOException("Cannot rename source: " + absoluteSrc + " to " + absoluteDst + " -" + ESameDirectoryOnly); } string from = absoluteSrc.GetName(); string to = absoluteDst.GetName(); client.ChangeWorkingDirectory(parentSrc); bool renamed = client.Rename(from, to); return(renamed); }
/// <exception cref="System.IO.IOException"/> public override FSDataInputStream Open(Path file, int bufferSize) { FTPClient client = Connect(); Path workDir = new Path(client.PrintWorkingDirectory()); Path absolute = MakeAbsolute(workDir, file); FileStatus fileStat = GetFileStatus(client, absolute); if (fileStat.IsDirectory()) { Disconnect(client); throw new FileNotFoundException("Path " + file + " is a directory."); } client.Allocate(bufferSize); Path parent = absolute.GetParent(); // Change to parent directory on the // server. Only then can we read the // file // on the server by opening up an InputStream. As a side effect the working // directory on the server is changed to the parent directory of the file. // The FTP client connection is closed when close() is called on the // FSDataInputStream. client.ChangeWorkingDirectory(parent.ToUri().GetPath()); InputStream @is = client.RetrieveFileStream(file.GetName()); FSDataInputStream fis = new FSDataInputStream(new FTPInputStream(@is, client, statistics )); if (!FTPReply.IsPositivePreliminary(client.GetReplyCode())) { // The ftpClient is an inconsistent state. Must close the stream // which in turn will logout and disconnect from FTP server fis.Close(); throw new IOException("Unable to open file: " + file + ", Aborting"); } return(fis); }