#define MAX_GETFILE_BUFFER (67108864/2) void get_file(struct shell_state *sh, char *local_path, char *remote_path, unsigned int remote_file_size) { FILE *f; unsigned char *buf; afc_file_ref ref; afc_error_t ret; // here we assume we are being passed absolute paths // in both remote and local paths ifVerbose cout << "AFCFileRefOpen: opening remote path '" << remote_path << "'" << endl; ret = AFCFileRefOpen(sh->conn, remote_path, 1, &ref); if (ret) { ifNotQuiet cout << "getfile: Failed to open remote file: " << ret << endl; return; } if (remote_file_size <= 0) remote_file_size = get_file_size(sh->conn, remote_path); ifVerbose cout << "AFCFileRefRead: reading " << remote_file_size << " bytes into buffer" << endl; unsigned int buffer_size = remote_file_size; if (remote_file_size > MAX_GETFILE_BUFFER) { ifVerbose cout << "File is too large for single call. Buffering."; buffer_size = MAX_GETFILE_BUFFER; } buf = (unsigned char *)malloc(buffer_size); if (!buf) { ifNotQuiet cout << "getfile: could not allocate buffer. Aborting." << endl; return; } unsigned int bytes_remaining = remote_file_size; D("Opening local_path: "< 0) { unsigned int read_size = bytes_remaining; if (read_size > buffer_size) read_size = buffer_size; bytes_remaining -= read_size; ifNotQuiet cout << "Reading " << read_size << " bytes, " << bytes_remaining << " bytes remain" << endl; D("AFCFileRead"); ret = AFCFileRefRead(sh->conn, ref, buf, &read_size); if (ret) { ifNotQuiet cout << "getfile: Failed to read from remote file: " << ret << endl; return; } D("writing local file."); fwrite(buf, read_size, 1, f); } ret = AFCFileRefClose(sh->conn, ref); if (ret) { ifNotQuiet cout << "getfile: Failed to close remote file: " << ret << endl; fclose(f); free(buf); return; } ifVerbose cout << "getfile: Writing file to local path '" << local_path << "'" << endl; D("closing local file."); fclose(f); D("freeing file buffer."); free(buf); ifVerbose cout << "getfile: Transfer successful." << endl; } void put_file(struct shell_state *sh, char *local_path, char *remote_path) { FILE *f; struct stat sb; unsigned char *buf; unsigned int size; afc_file_ref ref; std::string remotePathStr; afc_error_t ret; ifVerbose cout << "putfile: Opening local file '" << local_path << "'" << endl; f = fopen(local_path, "rb"); if (!f) { ifNotQuiet cout << "putfile: Failed to open local file '" << local_path << "'" << endl; return; } D("local file open."); // If remote_path isn't set, use cp semantics if(remote_path == NULL) { // putfile foo/bar // should create a file named bar in the current dir string local = local_path; if(local[local.length() - 1] == '/') { ifNotQuiet cout << "putfile: Writing directories is currently unsupported" << endl; return; } string::size_type lastSlash = local.find_last_of("/"); if(lastSlash == string::npos) { // simple filename in local_path remotePathStr = local_path; } else { remotePathStr = local.substr(lastSlash + 1); } } else { remotePathStr = remote_path; } D("remote path: "< MAX_GETFILE_BUFFER) { ifVerbose cout << "File is too large for single call. Buffering."; buffer_size = MAX_GETFILE_BUFFER; } buf = (unsigned char *)malloc(buffer_size); if (!buf) { ifNotQuiet cout << "putfile: could not allocate buffer. Aborting." << endl; return; } ifVerbose cout << "AFCFileRefOpen: opening remote file '" << remote_path << "'" << endl; ret = AFCFileRefOpen(sh->conn, remote_path, 3, &ref); unsigned int bytes_remaining = sb.st_size; while (bytes_remaining > 0) { unsigned int read_size = bytes_remaining; if (read_size > buffer_size) read_size = buffer_size; bytes_remaining -= read_size; D("reading local file."); fread(buf, read_size, 1, f); ifNotQuiet cout << "Writing " << read_size << " bytes, " << bytes_remaining << " bytes remain" << endl; D("AFCFileWrite"); ret = AFCFileRefWrite(sh->conn, ref, buf, read_size); if (ret) { ifNotQuiet cout << "putfile: Failed to write to remote file: " << ret << endl; return; } } ret = AFCFileRefClose(sh->conn, ref); if (ret) { ifNotQuiet cout << "putfile: Failed to close remote file: " << ret << endl; fclose(f); free(buf); return; } D("closing local file."); fclose(f); D("freeing file buffer."); free(buf); ifVerbose cout << "putfile: Transfer successful." << endl; }