diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc index 550313803f..71110796bf 100644 --- a/fs/vfs/main.cc +++ b/fs/vfs/main.cc @@ -833,6 +833,43 @@ mkdir(const char *pathname, mode_t mode) return -1; } +int mkdirat(int dirfd, const char *pathname, mode_t mode) +{ + mode = apply_umask(mode); + + if (pathname[0] == '/' || dirfd == AT_FDCWD) { + // Supplied path is either absolute or relative to cwd + return mkdir(pathname, mode); + } + + // Supplied path is relative to folder specified by dirfd + struct file *fp; + int error = fget(dirfd, &fp); + if (error) { + errno = error; + return -1; + } + + struct vnode *vp = fp->f_dentry->d_vnode; + vn_lock(vp); + + std::unique_ptr up (new char[PATH_MAX]); + char *p = up.get(); + + /* build absolute path */ + strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); + strlcat(p, fp->f_dentry->d_path, PATH_MAX); + strlcat(p, "/", PATH_MAX); + strlcat(p, pathname, PATH_MAX); + + error = mkdir(p, mode); + + vn_unlock(vp); + fdrop(fp); + + return error; +} + TRACEPOINT(trace_vfs_rmdir, "\"%s\"", const char*); TRACEPOINT(trace_vfs_rmdir_ret, ""); TRACEPOINT(trace_vfs_rmdir_err, "%d", int); diff --git a/libc/syscall_to_function.h b/libc/syscall_to_function.h index 73525cfa5f..6862fe349c 100644 --- a/libc/syscall_to_function.h +++ b/libc/syscall_to_function.h @@ -19,6 +19,8 @@ #define __OSV_TO_FUNCTION_SYS_writev writev #define __OSV_TO_FUNCTION_SYS_fstatat fstatat #define __OSV_TO_FUNCTION_SYS_unlinkat unlinkat +#define __OSV_TO_FUNCTION_SYS_mkdir mkdir +#define __OSV_TO_FUNCTION_SYS_mkdirat mkdirat #undef __syscall #define __syscall(sys_number, ...) (__OSV_TO_FUNCTION_##sys_number(__VA_ARGS__) < 0 ? -errno : 0) diff --git a/linux.cc b/linux.cc index 6eb9d3fe50..71ec8da1ac 100644 --- a/linux.cc +++ b/linux.cc @@ -447,6 +447,8 @@ long syscall(long number, ...) SYSCALL0(getpid); SYSCALL3(set_mempolicy, int, unsigned long *, unsigned long); SYSCALL3(sched_setaffinity_syscall, pid_t, unsigned, unsigned long *); + SYSCALL2(mkdir, char*, mode_t); + SYSCALL3(mkdirat, int, char*, mode_t); } debug_always("syscall(): unimplemented system call %d\n", number);