Ejemplo n.º 1
0
int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg)
{
	DWORD result = 0;
	LPSTR expanded = NULL;
	LPSTR baseDirectory = NULL;
	char tempDirectory[FS_MAX_PATH];

	_snprintf(tempDirectory, sizeof(tempDirectory), "%s", directory);

	/*
	 * If there is not wildcard mask on the directory, create a version of the
	 * directory with a mask appended
	 */
	if (strrchr(directory, '*') == NULL) {
		_snprintf(tempDirectory, sizeof(tempDirectory), "%s\\*",
				directory);

		baseDirectory = _strdup(directory);
		if (baseDirectory == NULL) {
			result = ERROR_NOT_ENOUGH_MEMORY;
			goto out;
		}

	} else {
		/*
		 * Otherwise, if it does have an asterisk, we need to scan back
		 * and find the base directory.  If there is no slash, it means
		 * we're listing the cwd.
		 */
		PCHAR slash = strrchr(directory, '\\');
		if (slash) {
			*slash = 0;
			baseDirectory = _strdup(directory);
			if (baseDirectory == NULL) {
				result = ERROR_NOT_ENOUGH_MEMORY;
				goto out;
			}
			*slash = '\\';
		}
	}

	expanded = fs_expand_path(tempDirectory);
	if (expanded == NULL) {
		result = ERROR_NOT_ENOUGH_MEMORY;
		goto out;
	}

	WIN32_FIND_DATAW data;
	wchar_t *path_w = utf8_to_wchar(expanded);
	if (path_w == NULL) {
		result = GetLastError();
		goto out;
	}

	HANDLE ctx = FindFirstFileW(path_w, &data);
	if (ctx == NULL) {
		result = GetLastError();
		goto out;
	}

	do {
		if (ctx == INVALID_HANDLE_VALUE) {
			result = GetLastError();
			break;
		}

		char *filename = wchar_to_utf8(data.cFileName);
		char *short_filename = wchar_to_utf8(data.cAlternateFileName);
		char path[FS_MAX_PATH];

		if (baseDirectory) {
			_snprintf(path, sizeof(path), "%s\\%s", baseDirectory, filename);
		} else {
			_snprintf(path, sizeof(path), "%s", filename);
		}

		cb(arg, filename, short_filename, path);

		free(filename);
		free(short_filename);

	} while (FindNextFileW(ctx, &data));

	/*
	 * Clean up resources
	 */
	FindClose(ctx);
	free(expanded);
out:
	free(baseDirectory);
	free(path_w);
	return result;
}
Ejemplo n.º 2
0
/*
 * Handles the open request for a file channel and returns a valid channel
 * identifier to the requestor if the file is opened successfully
 */
DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
{
	Packet *response = NULL;
	PCHAR filePath, mode;
	DWORD res = ERROR_SUCCESS;
	DWORD flags = 0;
	Channel *newChannel = NULL;
	PoolChannelOps chops = { 0 };
	FileContext *ctx;
	LPSTR expandedFilePath = NULL;

	do
	{
		// Allocate a response
		response = packet_create_response(packet);

		// Get the channel flags
		flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);

		// Allocate storage for the file context
		if (!(ctx = (FileContext *)malloc(sizeof(FileContext))))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Get the file path and the mode
		filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
		mode     = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_MODE);

		// No file path? bogus.
		if (!filePath)
		{
			res = ERROR_INVALID_PARAMETER;
			break;
		}

		// Expand the file path
		if (!(expandedFilePath = fs_expand_path(filePath)))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}
	
		if (!mode)
			mode = "rb";

		// Invalid file?
		if (!(ctx->fd = fopen(expandedFilePath, mode)))
		{
			res = GetLastError();
			break;
		}

		memset(&chops, 0, sizeof(chops));

		// Initialize the pool operation handlers
		chops.native.context = ctx;
		chops.native.write   = file_channel_write;
		chops.native.close   = file_channel_close;
		chops.read           = file_channel_read;
		chops.eof            = file_channel_eof;
		chops.seek           = file_channel_seek;
		chops.tell           = file_channel_tell;

		// Check the response allocation & allocate a un-connected
		// channel
		if ((!response) ||
		    (!(newChannel = channel_create_pool(0, flags,
				&chops))))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Add the channel identifier to the response
		packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, 
				channel_get_id(newChannel));

	} while (0);

	// Transmit the packet if it's valid
	packet_transmit_response(res, remote, response);

	// Clean up on failure
	if (res != ERROR_SUCCESS)
	{
		if (newChannel)
			channel_destroy(newChannel, NULL);
		if (ctx)
			free(ctx);
	}

	// Free the expanded file path if it was allocated
	if (expandedFilePath)
		free(expandedFilePath);

	return res;
}
Ejemplo n.º 3
0
/*
 * Gets the contents of a given directory path and returns the list of file
 * names to the requestor.
 *
 * TLVs:
 *
 * req: TLV_TYPE_DIRECTORY_PATH - The directory that should be listed
 */
DWORD request_fs_ls(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCSTR directory;
	DWORD result = ERROR_SUCCESS;
	LPSTR expanded = NULL, tempFile = NULL;
	DWORD tempFileSize = 0;
	LPSTR baseDirectory = NULL;
	struct meterp_stat buf;

	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);

	// Enumerate the directory if one was provided
	if (!directory)
		result = ERROR_INVALID_PARAMETER;
	else
	{
#ifdef _WIN32
		WIN32_FIND_DATA data;
		HANDLE ctx = NULL;
#else
		DIR *ctx;
		struct dirent *data;
#endif
		BOOLEAN freeDirectory = FALSE;
		LPSTR tempDirectory = (LPSTR)directory;

#ifdef _WIN32
		// If there is not wildcard mask on the directory, create a version of the
		// directory with a mask appended
		if (!strrchr(directory, '*'))
		{
			if (!(tempDirectory = (LPSTR)malloc(strlen(directory) + 3)))
			{
				result = ERROR_NOT_ENOUGH_MEMORY;
				goto out;
			}

			sprintf(tempDirectory, "%s\\*", directory);	

			// Dupe!
			if (!(baseDirectory = _strdup(directory)))
			{
				result = ERROR_NOT_ENOUGH_MEMORY;
				goto out;
			}
		}
		// Otherwise, if it does have an asterisk, we need to scan back and find
		// the base directory.  If there is no slash, it means we're listing the
		// cwd.
		else
		{
			PCHAR slash = strrchr(directory, '\\');

			if (slash)
			{
				*slash = 0;

				if (!(baseDirectory = _strdup(directory)))
				{
					result = ERROR_NOT_ENOUGH_MEMORY;
					goto out;
				}

				*slash = '\\';
			}
		}

		// Expand the path
		if (!(expanded = fs_expand_path(tempDirectory)))
		{
			result = ERROR_NOT_ENOUGH_MEMORY;
			goto out;
		}

		// Start the find operation
		ctx = FindFirstFile(expanded, &data);

 #define DF_NAME data.cFileName
#else
		expanded = 0;
		ctx = opendir(tempDirectory);
		if(ctx == NULL)
		{
		  result = errno;
		  goto out;
		}
		data = readdir(ctx);
		if (!(baseDirectory = _strdup(directory)))
		{
			result = ERROR_NOT_ENOUGH_MEMORY;
			goto out;
		}
	      
 #define DF_NAME data->d_name
#endif

		do
		{
			DWORD fullSize = (baseDirectory ? strlen(baseDirectory) : 0) + strlen(DF_NAME) + 2;

			// No context?  Sucktastic
			if (ctx == INVALID_HANDLE_VALUE)
			{
				result = GetLastError();
				break;
			}

			// Allocate temporary storage to stat the file
			if ((!tempFile) ||
			    (tempFileSize < fullSize))
			{
				if (tempFile)
					free(tempFile);

				// No memory means we suck a lot like spoon's mom
				if (!(tempFile = (LPSTR)malloc(fullSize)))
				{
					result = ERROR_NOT_ENOUGH_MEMORY;
					break;
				}

				// Update the tempFileSize so that we don't allocate if we don't
				// need to like a true efficient ninja
				tempFileSize = fullSize;
			}

			// Build the full path
			if (baseDirectory)
#ifdef _WIN32
				sprintf(tempFile, "%s\\%s", baseDirectory, DF_NAME);
#else
				sprintf(tempFile, "%s/%s", baseDirectory, DF_NAME);
#endif
			else
				sprintf(tempFile, "%s", DF_NAME);

			// Add the file name to the response
			packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, 
					DF_NAME);
			// Add the full path
			packet_add_tlv_string(response, TLV_TYPE_FILE_PATH,
					tempFile);

			// Stat the file to get more information about it.
			if (fs_stat(tempFile, &buf) >= 0)
				packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
						sizeof(buf));

#ifdef _WIN32
		} while (FindNextFile(ctx, &data));
#else
	        } while (data = readdir(ctx));