+
+ return(status);
+}
+
+static int
+download_dir_internal(struct sftp_conn *conn, char *src, char *dst,
+ Attrib *dirattrib, int pflag, int printflag, int depth)
+{
+ int i, ret = 0;
+ SFTP_DIRENT **dir_entries;
+ char *filename, *new_src, *new_dst;
+ mode_t mode = 0777;
+
+ if (depth >= MAX_DIR_DEPTH) {
+ error("Maximum directory depth exceeded: %d levels", depth);
+ return -1;
+ }
+
+ if (dirattrib == NULL &&
+ (dirattrib = do_stat(conn, src, 1)) == NULL) {
+ error("Unable to stat remote directory \"%s\"", src);
+ return -1;
+ }
+ if (!S_ISDIR(dirattrib->perm)) {
+ error("\"%s\" is not a directory", src);
+ return -1;
+ }
+ if (printflag)
+ printf("Retrieving %s\n", src);
+
+ if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
+ mode = dirattrib->perm & 01777;
+ else {
+ debug("Server did not send permissions for "
+ "directory \"%s\"", dst);
+ }
+
+ if (mkdir(dst, mode) == -1 && errno != EEXIST) {
+ error("mkdir %s: %s", dst, strerror(errno));
+ return -1;
+ }
+
+ if (do_readdir(conn, src, &dir_entries) == -1) {
+ error("%s: Failed to get directory contents", src);
+ return -1;
+ }
+
+ for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
+ filename = dir_entries[i]->filename;
+
+ new_dst = path_append(dst, filename);
+ new_src = path_append(src, filename);
+
+ if (S_ISDIR(dir_entries[i]->a.perm)) {
+ if (strcmp(filename, ".") == 0 ||
+ strcmp(filename, "..") == 0)
+ continue;
+ if (download_dir_internal(conn, new_src, new_dst,
+ &(dir_entries[i]->a), pflag, printflag,
+ depth + 1) == -1)
+ ret = -1;
+ } else if (S_ISREG(dir_entries[i]->a.perm) ) {
+ if (do_download(conn, new_src, new_dst,
+ &(dir_entries[i]->a), pflag) == -1) {
+ error("Download of file %s to %s failed",
+ new_src, new_dst);
+ ret = -1;
+ }
+ } else
+ logit("%s: not a regular file\n", new_src);
+
+ xfree(new_dst);
+ xfree(new_src);
+ }
+
+ if (pflag) {
+ if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+ struct timeval tv[2];
+ tv[0].tv_sec = dirattrib->atime;
+ tv[1].tv_sec = dirattrib->mtime;
+ tv[0].tv_usec = tv[1].tv_usec = 0;
+ if (utimes(dst, tv) == -1)
+ error("Can't set times on \"%s\": %s",
+ dst, strerror(errno));
+ } else
+ debug("Server did not send times for directory "
+ "\"%s\"", dst);
+ }
+
+ free_sftp_dirents(dir_entries);
+
+ return ret;
+}
+
+int
+download_dir(struct sftp_conn *conn, char *src, char *dst,
+ Attrib *dirattrib, int pflag, int printflag)
+{
+ char *src_canon;
+ int ret;
+
+ if ((src_canon = do_realpath(conn, src)) == NULL) {
+ error("Unable to canonicalise path \"%s\"", src);
+ return -1;
+ }
+
+ ret = download_dir_internal(conn, src_canon, dst,
+ dirattrib, pflag, printflag, 0);
+ xfree(src_canon);
+ return ret;