Sherlock-Holo / fuse3

an async version fuse library for rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use Timespec instead of SystemTime in raw::reply::FileAttr

asomers opened this issue · comments

std::time::SystemTime may be convenient for passthrough file systems, where the time will come from std::fs::Metadata already in that format. But it's not so convenient for raw file systems. Raw file systems more likely store the timestamps in a serialized format. Converting between serialized timestamps and SystemTime requires needless comparisons with UNIX_EPOCH. It would be more convenient if raw::reply::FileAttr used libc::timespec, which is pretty close to what the FUSE protocol wants anyway.

Actually, the problem is worse than I initially thought. Currently, fuse3 does not allow a raw file system to express a timestamp older than the Epoch. Since Duration is always positive, the code in fuse_attr::from in raw/reply.rs, line 63, will change all negative timestamps into 0.

BTW, even thought the FUSE ABI uses unsigned numbers everywhere, the seconds fields are actually signed. The ABI is just defined wrong. The get cast to signed time_t in C.

there must be some files are earlier than 1970-1-1, so provide a way to create a timestamp that is earlier than Epoch is a good idea.
However, limited by the Linux fuse protocol, we can't mount an fs and it contains a file which creation time is earlier than Epoch. Maybe we should document it on the new struct Timestamp

Sure, it's possible to have a FUSE-mounted file with timestamps older than the Epoch. The kernel header is just kind of wrong. The unsigned timestamp fields in struct fuse_attr are actually treated as signed by the kernel.

struct fuse_attr {
	uint64_t	ino;
	uint64_t	size;
	uint64_t	blocks;
	uint64_t	atime;
	uint64_t	mtime;
	uint64_t	ctime;
	uint32_t	atimensec;
	uint32_t	mtimensec;
	uint32_t	ctimensec;
	uint32_t	mode;
	uint32_t	nlink;
	uint32_t	uid;
	uint32_t	gid;
	uint32_t	rdev;
	uint32_t	blksize;
	uint32_t	padding;
};