Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CC ?= cc
HOST_CFLAGS = -g -O1 -DPC_SIDE -D_FILE_OFFSET_BITS=64 -I../usbhostfs -I../usbhostfs_pc $(shell pkg-config --cflags libusb-1.0)
HOST_LIBS = -lpthread $(shell pkg-config --libs libusb-1.0)

.PHONY: test
test:
@bin=$$(mktemp /tmp/psplinkusb-hostfs-test.XXXXXX); \
trap 'rm -f "$$bin"' EXIT; \
$(CC) $(HOST_CFLAGS) -o "$$bin" hostfs_directory_test.c $(HOST_LIBS) && "$$bin"
100 changes: 100 additions & 0 deletions tests/hostfs_directory_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* HostFS directory regression test. Include the implementation so its
* otherwise-internal directory helpers can be exercised without USB hardware.
*/
#define main usbhostfs_pc_main
#include "../usbhostfs_pc/main.c"
#undef main

#include <assert.h>

/* Exercise the on-wire directory response without a physical USB device. */
static int usb_write_count;
static struct HostFsDreadResp usb_dread_response;
static SceIoDirent usb_dread_entry;

int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev, unsigned char endpoint,
unsigned char *data, int length, int *transferred, unsigned int timeout)
{
(void) dev;
(void) timeout;
assert(endpoint == 0x02);
if(usb_write_count == 0)
{
assert(length == sizeof(usb_dread_response));
memcpy(&usb_dread_response, data, length);
}
else if(usb_write_count == 1)
{
assert(length == sizeof(usb_dread_entry));
memcpy(&usb_dread_entry, data, length);
}
else
{
assert(0 && "unexpected USB transfer");
}
usb_write_count++;
*transferred = length;
return LIBUSB_SUCCESS;
}

int main(void)
{
char root[] = "/tmp/psplinkusb-dir-XXXXXX";
char linkpath[PATH_MAX];
const char *iterations = getenv("HOSTFS_TEST_ITERATIONS");
int repetitions = iterations ? atoi(iterations) : 1000;
int did;
int found_link = 0;
int i;

assert(repetitions > 0);
assert(mkdtemp(root) != NULL);
assert(snprintf(linkpath, sizeof(linkpath), "%s/broken-link", root) < (int)sizeof(linkpath));
assert(symlink("missing-target", linkpath) == 0);

init_hostfs();
strcpy(g_drives[0].rootdir, root);

did = dir_open(0, "/");
assert(did >= 0);
for(i = 0; i < open_dirs[did].count; i++)
{
if(strcmp(open_dirs[did].pDir[i].name, "broken-link") == 0)
{
found_link = 1;
assert(LE32(open_dirs[did].pDir[i].stat.mode) & FIO_S_IFLNK);
}
}
assert(found_link);
{
struct HostFsDreadCmd cmd;
int ret;
memset(&cmd, 0, sizeof(cmd));
cmd.cmd.magic = LE32(HOSTFS_MAGIC);
cmd.cmd.command = LE32(HOSTFS_CMD_DREAD);
cmd.did = LE32(did);
ret = handle_dread(NULL, &cmd, sizeof(cmd));
assert(ret == sizeof(usb_dread_entry));
assert(usb_write_count == 2);
assert(LE32(usb_dread_response.cmd.magic) == HOSTFS_MAGIC);
assert(LE32(usb_dread_response.cmd.command) == HOSTFS_CMD_DREAD);
assert(LE32(usb_dread_response.cmd.extralen) == sizeof(SceIoDirent));
assert(LE32(usb_dread_response.res) > 0);
assert(usb_dread_entry.name[0] != '\0');
}
assert(dir_close(did) == 0);

/* Run this under a leak sanitizer to catch scandir allocations on success. */
for(i = 0; i < repetitions; i++)
{
did = dir_open(0, "/");
assert(did >= 0);
assert(dir_close(did) == 0);
}

assert(unlink(linkpath) == 0);
assert(rmdir(root) == 0);
puts("HostFS directory test passed");
return 0;
}
16 changes: 8 additions & 8 deletions usbhostfs_pc/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,8 @@ int fill_stat(const char *dirname, const char *name, SceIoStat *scestat)
strcpy(path, name);
}

if(stat(path, &st) < 0)
/* Preserve dangling symlinks as directory entries rather than failing the listing. */
if(lstat(path, &st) < 0)
{
fprintf(stderr, "Couldn't stat file %s (%s)\n", path, strerror(errno));
return GETERROR(errno);
Expand Down Expand Up @@ -804,21 +805,20 @@ int dir_open(int drive, const char *dirname)
else
{
free(open_dirs[did].pDir);
open_dirs[did].pDir = NULL;
}
}
else
{
fprintf(stderr, "Could not allocate memory for directories\n");
}

if(ret < 0)
/* scandir owns these allocations even when the listing succeeds. */
for(i = 0; i < dirnum; i++)
{
for(i = 0; i < dirnum; i++)
{
free(entries[i]);
}
free(entries);
free(entries[i]);
}
free(entries);
}
while(0);

Expand Down Expand Up @@ -1230,7 +1230,7 @@ int handle_dread(libusb_device_handle *dev, struct HostFsDreadCmd *cmd, int cmdl

memset(&resp, 0, sizeof(resp));
resp.cmd.magic = LE32(HOSTFS_MAGIC);
resp.cmd.command = LE32(HOSTFS_CMD_READ);
resp.cmd.command = LE32(HOSTFS_CMD_DREAD);
Comment thread
sharkwouter marked this conversation as resolved.
Resolved
resp.res = LE32(-1);

do
Expand Down
Loading