Standard C library functions in WASM: stat, opendir, access, fseek

Version: 1.5.9.0

SDK Version: 1.4.2

Frequency: Consistently

Severity: High

Bug description:

C function stat doesn’t work on directories (it works correctly on files)

Repro steps:

In a WASM standalone module, if I do “stat” on any dir of my package I get error 29:

struct stat st;
auto result = stat("./modules", &st);

if (result == -1) {	
	int error_code = errno;

	printf("  FAILURE: stat() returned -1.\n");
	printf("  Error Code (errno): %d\n", error_code);
	printf("  Error Message: %s\n", strerror(error_code));
}
else {	
	printf("  SUCCESS: stat() returned 0.\n");	
}

result is always -1 with errno 29

1 Like

Hi @MaxHype

I have just checked the code and indeed we never implemented the WASI function “path_filestat_get” for file descriptors targeting directories.
We’ll see if we can add this in the future but I have to say this rather low priority at this stage.

Best regards,

Eric / Asobo

1 Like

Ok thank you @EPellissier,
in the meantime I’ve found a workaround using opendir function (that instead uses “__wasilibc_nocwd_opendirat” and “__wasi_path_open”)

another low priority similar issue is with fseek and negative offsets:

auto f = fopen("./file.dat", "rb");
auto result = fseek(f, -2, SEEK_END);
if (result == -1)
{
	fprintf(stderr, "Failed to seek in file ./file.dat: %s\n", strerror(errno));
	fclose(f);
	return;
}

result is always -1 with errno 29

the workaround is avoiding negative offset using SEEK_SET with absolute position from the start calculated using file size

1 Like

@EPellissier unfortunately I still haven’t found a reliable way to check if a directory exist.
I noticed that opendir never returns NULL even if the directory is not existent:

DIR* dir = opendir("./modules");
if (dir) {
	fprintf(stdout, "Directory ./modules opened successfully.\n");
	closedir(dir);
}
else {
	fprintf(stderr, "Failed to open directory ./modules: %s\n", strerror(errno));
	return;
}

dir = opendir("./notexist");
if (dir) {
	fprintf(stdout, "Directory ./notexist opened successfully.\n");
	closedir(dir);
}
else {
	fprintf(stderr, "Failed to open directory ./notexist: %s\n", strerror(errno));
	return;
}

In the example /modules is opened successfully, but also /notexist is opened successfully (wrongly)

Moreover, no luck also trying with access function:

auto acc = access("./modules", F_OK); // Check if the directory exists
if (acc == 0) {
	fprintf(stdout, "Access Directory ./modules exists.\n");
}
else {
	fprintf(stderr, "Access Directory ./modules does not exist: %s %d\n", strerror(errno), errno); //EIO
	return;
}

this last returns always -1 with errno 29