All pastes #733276 Raw Edit

Stuff

public text v1 · immutable
·published 2007-10-11 17:57 UTC
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;
}