/// <summary> /// Creates a remote directory asynchronously /// </summary> /// <param name="path">The full or relative path to the new remote directory</param> /// <param name="force">Try to create the whole path if the preceding directories do not exist</param> /// <param name="token">The token that can be used to cancel the entire process</param> /// <returns>True if directory was created, false if it was skipped</returns> public async Task <bool> CreateDirectoryAsync(string path, bool force, CancellationToken token = default(CancellationToken)) { // don't verify args as blank/null path is OK //if (path.IsBlank()) // throw new ArgumentException("Required parameter is null or blank.", "path"); path = path.GetFtpPath(); LogFunc(nameof(CreateDirectoryAsync), new object[] { path, force }); FtpReply reply; // cannot create root or working directory if (path.IsFtpRootDirectory()) { return(false); } // server-specific directory creation // ask the server handler to create a directory if (ServerHandler != null) { if (await ServerHandler.CreateDirectoryAsync(this, path, path, force, token)) { return(true); } } path = path.TrimEnd('/'); if (force && !await DirectoryExistsAsync(path.GetFtpDirectoryName(), token)) { LogStatus(FtpTraceLevel.Verbose, "Create non-existent parent directory: " + path.GetFtpDirectoryName()); await CreateDirectoryAsync(path.GetFtpDirectoryName(), true, token); } // fix: improve performance by skipping the directory exists check /*else if (await DirectoryExistsAsync(path, token)) { * return false; * }*/ LogStatus(FtpTraceLevel.Verbose, "CreateDirectory " + path); if (!(reply = await ExecuteAsync("MKD " + path, token)).Success) { // if the error indicates the directory already exists, its not an error if (reply.Code == "550") { return(false); } if (reply.Code[0] == '5' && reply.Message.IsKnownError(FtpServerStrings.folderExists)) { return(false); } throw new FtpCommandException(reply); } return(true); }