+ /* Override umask and utimes if asked */
+ if (pflag)
+ do_fsetstat(conn, handle, handle_len, &a);
+
+ if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
+ status = -1;
+ xfree(handle);
+
+ return status;
+}
+
+static int
+upload_dir_internal(struct sftp_conn *conn, char *src, char *dst,
+ int pflag, int printflag, int depth)
+{
+ int ret = 0, status;
+ DIR *dirp;
+ struct dirent *dp;
+ char *filename, *new_src, *new_dst;
+ struct stat sb;
+ Attrib a;
+
+ if (depth >= MAX_DIR_DEPTH) {
+ error("Maximum directory depth exceeded: %d levels", depth);
+ return -1;
+ }
+
+ if (stat(src, &sb) == -1) {
+ error("Couldn't stat directory \"%s\": %s",
+ src, strerror(errno));
+ return -1;
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ error("\"%s\" is not a directory", src);
+ return -1;
+ }
+ if (printflag)
+ printf("Entering %s\n", src);
+
+ attrib_clear(&a);
+ stat_to_attrib(&sb, &a);
+ a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
+ a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
+ a.perm &= 01777;
+ if (!pflag)
+ a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
+
+ status = do_mkdir(conn, dst, &a, 0);
+ /*
+ * we lack a portable status for errno EEXIST,
+ * so if we get a SSH2_FX_FAILURE back we must check
+ * if it was created successfully.
+ */
+ if (status != SSH2_FX_OK) {
+ if (status != SSH2_FX_FAILURE)
+ return -1;
+ if (do_stat(conn, dst, 0) == NULL)
+ return -1;
+ }
+
+ if ((dirp = opendir(src)) == NULL) {
+ error("Failed to open dir \"%s\": %s", src, strerror(errno));
+ return -1;
+ }
+
+ while (((dp = readdir(dirp)) != NULL) && !interrupted) {
+ if (dp->d_ino == 0)
+ continue;
+ filename = dp->d_name;
+ new_dst = path_append(dst, filename);
+ new_src = path_append(src, filename);
+
+ if (lstat(new_src, &sb) == -1) {
+ logit("%s: lstat failed: %s", filename,
+ strerror(errno));
+ ret = -1;
+ } else if (S_ISDIR(sb.st_mode)) {
+ if (strcmp(filename, ".") == 0 ||
+ strcmp(filename, "..") == 0)
+ continue;
+
+ if (upload_dir_internal(conn, new_src, new_dst,
+ pflag, depth + 1, printflag) == -1)
+ ret = -1;
+ } else if (S_ISREG(sb.st_mode)) {
+ if (do_upload(conn, new_src, new_dst, pflag) == -1) {
+ error("Uploading of file %s to %s failed!",
+ new_src, new_dst);
+ ret = -1;
+ }
+ } else
+ logit("%s: not a regular file\n", filename);
+ xfree(new_dst);
+ xfree(new_src);
+ }
+
+ do_setstat(conn, dst, &a);
+
+ (void) closedir(dirp);
+ return ret;