Open oatgnauh opened 11 months ago
If host is 64 bit so there that stat struct probably uses 64 bit variables while perhaps emscripten use 32 bit (or the other way around). Why the emscripten version has padding I can not say but that seems to be the case.
Perhaps do a hexdump of the entire struct to see what that looks like.
One can experiment with printing the addresses. That will tell where they are expected (although not where they actually are). printf("sb.st_mode %x %p %p\n", sb.st_mode, &sb, &sb.st_mode);
When I try it this, tells me that in one st_mode is expected at offset 0xC and at offset 0x18 in the other.
To be more precise you may need to define a guest struct for stat and copy the content data member by member:
So these members:
struct translated_stat { dev_t st_dev // Device ID of device containing file. (perhaps padding here or not) ino_t st_ino // File serial number. mode_t st_mode // Mode of file (see below).
and so on.
Copied one by one.
host.st_dev = guest.st_dev; host.st_ino = guest.st_ino; host.st_mode = guest.st_mode;
and so on.
Or copy it (memcpy style) to the translate_struct and then data appears as aligned. Or I totally missed what the question was.
Indeed emscripten defines all its own types such as struct stat
.
System headers such as /usr/include/x86_64-linux-gnu/bits/stat.h
, just like system libraries, cannot be used with emscripten. Those are designed for the host system, and won't work with emscripten or any other cross compiler.
Indeed emscripten defines all its own types such as
struct stat
.System headers such as
/usr/include/x86_64-linux-gnu/bits/stat.h
, just like system libraries, cannot be used with emscripten. Those are designed for the host system, and won't work with emscripten or any other cross compiler.
so, If I have to use such system libraries, the inlcuding headers must be replace <sys/XX.h> with <bits/XX.h> ? otherwise I have to transfer emscripten's define to system define, just like:
struct stat emsdk;
lstat(filename.c_str(), &emsdk);
struct stat system;
system.st_dev = emsdk.st_dev;
system.st_mode = emsdk.st_mode;
...
This seems very inelegant
I'm not sure what you are asking but I think the answer is no. Both your system compiler and emscripten contains defintions of struct stat
and the lstat
function. In both cases you should include <sys/stat.h>
I believe. But emscripten's version of this header is specific to emscripten and your OS version is specific to your OS. You can't mix them in single program.
You can see both stat
and lstat
defined in emscripten here: https://github.com/emscripten-core/emscripten/blob/e57438135ed9f8ded5f01cea124d98156bb29c7f/system/lib/libc/musl/include/sys/stat.h#L73-L75
I'm not sure what you are asking but I think the answer is no. Both your system compiler and emscripten contains defintions of
struct stat
and thelstat
function. In both cases you should include<sys/stat.h>
I believe. But emscripten's version of this header is specific to emscripten and your OS version is specific to your OS. You can't mix them in single program.You can see both
stat
andlstat
defined in emscripten here:
sorry for border you, I should make my question clear. my problem is:
When I gave a legal path to lstat
, I expected stat.st_size
to be greater than zero, but in fact it is not.
And when I printed other variables in the stat structure,
printf("buf:%p, exists:%d, buf.st_mode:%d, buf.st_size:%lld,sizeptr:%p, diff:%d, st_dev:%d, st_ino:%d, st_mode:%d",
&statbuf, ret, statbuf.st_mode, statbuf.st_size, &(statbuf.st_size), offsetof(struct stat, st_size), offsetof(struct stat, st_dev), offsetof(struct stat, st_ino), offsetof(struct stat, st_mode))
I found that the values of the same members were printed inconsistently in the user code and emsdk's stat implementation. (you can check the print result on my first post img.
To put it simply, I cannot use the stat function normally. Because I saw that the distribution of stat members inside emscripten is inconsistent with the system library, I suspect that there is a problem with the data conversion here.
I wonder inside __syscall_newfstatat,
int __syscall_newfstatat(int dirfd, intptr_t path, intptr_t buf, int flags) {
// Only accept valid flags.
if (flags & ~(AT_EMPTY_PATH | AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW)) {
// TODO: Test this case.
return -EINVAL;
}
auto parsed = path::getFileAt(dirfd, (char*)path, flags);
if (auto err = parsed.getError()) {
return err;
}
auto file = parsed.getFile();
// Extract the information from the file.
auto lockedFile = file->locked();
auto buffer = (struct stat*)buf;
off_t size = lockedFile.getSize();
if (size < 0) {
return size;
}
buffer->st_size = size;
// ATTN: hard-coded constant values are copied from the existing JS file
// system. Specific values were chosen to match existing library_fs.js
// values.
// ID of device containing file: Hardcode 1 for now, no meaning at the
// moment for Emscripten.
buffer->st_dev = 1;
buffer->st_mode = lockedFile.getMode();
buffer->st_ino = file->getIno();
// The number of hard links is 1 since they are unsupported.
buffer->st_nlink = 1;
buffer->st_uid = 0;
buffer->st_gid = 0;
// Device ID (if special file) No meaning right now for Emscripten.
buffer->st_rdev = 0;
// The syscall docs state this is hardcoded to # of 512 byte blocks.
buffer->st_blocks = (buffer->st_size + 511) / 512;
// Specifies the preferred blocksize for efficient disk I/O.
buffer->st_blksize = 4096;
buffer->st_atim.tv_sec = lockedFile.getATime();
buffer->st_mtim.tv_sec = lockedFile.getMTime();
buffer->st_ctim.tv_sec = lockedFile.getCTime();
return __WASI_ERRNO_SUCCESS;
}
auto buffer = (struct stat*)buf;
Is this buffer defined by emsdk itself or the system library?
If host is 64 bit so there that stat struct probably uses 64 bit variables while perhaps emscripten use 32 bit (or the other way around). Why the emscripten version has padding I can not say but that seems to be the case.
Perhaps do a hexdump of the entire struct to see what that looks like.
One can experiment with printing the addresses. That will tell where they are expected (although not where they actually are). printf("sb.st_mode %x %p %p\n", sb.st_mode, &sb, &sb.st_mode);
When I try it this, tells me that in one st_mode is expected at offset 0xC and at offset 0x18 in the other.
To be more precise you may need to define a guest struct for stat and copy the content data member by member:
So these members:
struct translated_stat { dev_t st_dev // Device ID of device containing file. (perhaps padding here or not) ino_t st_ino // File serial number. mode_t st_mode // Mode of file (see below).
and so on.
Copied one by one.
host.st_dev = guest.st_dev; host.st_ino = guest.st_ino; host.st_mode = guest.st_mode;
and so on.
Or copy it (memcpy style) to the translate_struct and then data appears as aligned. Or I totally missed what the question was.
I have print st_size address, you can check the image i post first. key word is sizeptr, both print inside emscripten and my code
When I gave a legal path to lstat
What do you mean by legal path here? Are you sure the file exists in the emscripten virtual file system? Are you aware that emscripten does not have direct access to the host filesystem. See: https://emscripten.org/docs/api_reference/Filesystem-API.html
When I gave a legal path to lstat
What do you mean by legal path here? Are you sure the file exists in the emscripten virtual file system? Are you aware that emscripten does not have direct access to the host filesystem. See: https://emscripten.org/docs/api_reference/Filesystem-API.html
Yes I am sure, my application is running on browser, the path I passing is a FS file path. And I can use js interface FS
to verify it's legality. I am quite sure the path I pass to lstat is a file
Can you check what value is being returned by lstat
? Is it returning zero?
What is VEFS in the above screenshot?
Oh wait I can see in your screenshot that its printing exists: false
which means stat is indeed returning zero.
Going back to the original question, are are thinking that your user code is not using emscripten stat struct layout?
If you are somehow including /usr/include/x86_64-linux-gnu/bits/stat.h
that would be real source of problem. That header should never be included in any emscripten-built program. That is a host-specific header and won't work with emscripten.
Version of emscripten/emsdk: 3.1.34 I am writting a function to check the given path is a file, here is code:
then I find out that given a file path, return false, pretty odd. Thus I print addr of stat, both my code and emscripten inside is the same, check the image below:
which show different offset of the same member. and I alse find out that accorrding to the offset of
st_mode
andst_ino
, emscripten is using it's own stat definition instead of <sys/stat.h>, check below:Thus,
st_mode
andst_size
is correct in emscripten print, but wrong at my code. you can see stat defined in system lib /usr/include/x86_64-linux-gnu/bits/stat.hHow can I fix it? I try to using
but comes with some compile error I don't think it is good idea to solve it. pls help~