rendered paste body#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: "<<local_path);
f = fopen(local_path, "w+b");
if (f == NULL) {
ifNotQuiet cout << "getfile: Failed to open local file '" << local_path << "'" << endl;;
free(buf);
return;
}
while (bytes_remaining > 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: "<<remote_path);
remote_path = (char *) remotePathStr.c_str();
size = fstat(fileno(f), &sb);
D("local fileno: "<< fileno(f));
// AFCFileRefWrite: Writing to remote file
// putfile: Failed to write to remote file: 11
// is usually caused by trying to write a file with size 0
if( sb.st_size == 0 )
{
ifNotQuiet cout << "putfile: Cannot write file with size " << sb.st_size << endl;
return;
}
unsigned int buffer_size = sb.st_size;
if (sb.st_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 << "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;
}