Commit dfc5d9c4 authored by sevenuz's avatar sevenuz
Browse files

fix dir fd

parent 10c7999c
Loading
Loading
Loading
Loading
Loading
+14 −11
Original line number Diff line number Diff line
@@ -213,36 +213,39 @@ hook_openat(int dirfd, const char* cpath, int flags, mode_t mode) {
            if(flags & O_DIRECTORY) {
                // Caller explicitly requests a directory: route via FUSE.
                // No metadata RPC needed — flag is authoritative.
                // Register as OpenDir so hook_close issues SYS_close on the
                // kernel fd (not gkfs_close) and hook_fchdir finds a valid
                // OpenDir instead of returning -EBADF.
                int fd = gsl::narrow_cast<int>(syscall_no_intercept_wrapper(
                        SYS_openat, dirfd, cpath, flags, mode));
                if(fd < 0) {
                    return fd;
                }
                CTX->file_map()->add(
                        fd, std::make_shared<gkfs::filemap::OpenFile>(resolved,
                                                                      flags));
                        fd, std::make_shared<gkfs::filemap::OpenDir>(resolved));
                return fd;
            }
            if(flags & (O_WRONLY | O_RDWR | O_CREAT)) {
                // Write or create flags imply a regular file: intercept directly.
            if(flags & O_CREAT) {
                // O_CREAT always creates a new file in the intercept namespace.
                return with_errno(
                        gkfs::syscall::gkfs_open(resolved, mode, flags));
            }
            // O_RDONLY without O_DIRECTORY: ambiguous (could be a regular file
            // or a dir/FUSE-only entry created by a non-intercepted process).
            // Try intercept first; on ENOENT fall back to FUSE — no upfront stat.
            // No O_CREAT, no O_DIRECTORY: could be a regular file, a
            // directory opened without O_DIRECTORY, or a FIFO/special file
            // created via mknodat (which bypasses intercept and goes to FUSE).
            // Try intercept first; fall back to FUSE on ENOENT (entry not in
            // intercept namespace) or EISDIR (path is a dir, which lives in
            // FUSE). Do not register FUSE-fallback fds in file_map so that
            // subsequent ops (fstat, read) are served by the kernel/FUSE.
            {
                int ret = gkfs::syscall::gkfs_open(resolved, mode, flags);
                if(ret >= 0) {
                    return ret;
                }
                int saved_errno = errno;
                if(saved_errno != ENOENT) {
                if(saved_errno != ENOENT && saved_errno != EISDIR) {
                    return -saved_errno;
                }
                // Not in intercept namespace: let FUSE handle it (dir or
                // entry created outside intercept). Do not register in
                // file_map so that subsequent ops (fstat, read) go to kernel.
                return gsl::narrow_cast<int>(syscall_no_intercept_wrapper(
                        SYS_openat, dirfd, cpath, flags, mode));
            }