Skip to content

Commit

Permalink
capi: add Root::mkdir_all bindings
Browse files Browse the repository at this point in the history
Signed-off-by: Aleksa Sarai <[email protected]>
  • Loading branch information
cyphar committed Aug 12, 2024
1 parent 043987d commit 0aeccc6
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 0 deletions.
7 changes: 7 additions & 0 deletions contrib/bindings/python/pathrs/_pathrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ def mkdir(self, path, mode):
if err < 0:
raise Error._fetch(err) or INTERNAL_ERROR

def mkdir_all(self, path, mode):
path = _cstr(path)
fd = libpathrs_so.pathrs_mkdir_all(self.fileno(), path, mode)
if fd < 0:
raise Error._fetch(fd) or INTERNAL_ERROR
return Handle(fd)

def mknod(self, path, mode, dev=0):
path = _cstr(path)
err = libpathrs_so.pathrs_mknod(self.fileno(), path, mode, dev)
Expand Down
8 changes: 8 additions & 0 deletions go-pathrs/libpathrs_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ func pathrsMkdir(rootFd uintptr, path string, mode uint32) error {
return fetchError(err)
}

func pathrsMkdirAll(rootFd uintptr, path string, mode uint32) (uintptr, error) {
cPath := C.CString(path)
defer C.free(unsafe.Pointer(cPath))

fd := C.pathrs_mkdir_all(C.int(rootFd), cPath, C.uint(mode))
return uintptr(fd), fetchError(fd)
}

func pathrsMknod(rootFd uintptr, path string, mode uint32, dev uint64) error {
cPath := C.CString(path)
defer C.free(unsafe.Pointer(cPath))
Expand Down
24 changes: 24 additions & 0 deletions go-pathrs/root_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,30 @@ func (r *Root) Mkdir(path string, mode os.FileMode) error {
return err
}

// MkdirAll creates a directory (and any parent path components if they don't
// exist) within a Root's directory tree. The provided mode is used for any
// directories created by this function (the process's umask applies).
//
// This is effectively equivalent to os.MkdirAll.
func (r *Root) MkdirAll(path string, mode os.FileMode) (*Handle, error) {
unixMode, err := toUnixMode(mode)
if err != nil {
return nil, err
}

return withFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
handleFd, err := pathrsMkdirAll(rootFd, path, unixMode)
if err != nil {
return nil, err
}
handleFile, err := mkFile(uintptr(handleFd))
if err != nil {
return nil, err
}
return &Handle{inner: handleFile}, err
})
}

// Mknod creates a new device inode of the given type within a Root's directory
// tree. The provided mode is used for the new directory (the process's umask
// applies).
Expand Down
16 changes: 16 additions & 0 deletions include/pathrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,22 @@ int pathrs_creat(int root_fd, const char *path, int flags, unsigned int mode);
*/
int pathrs_mkdir(int root_fd, const char *path, unsigned int mode);

/**
* Create a new directory (and any of its path components if they don't exist)
* within the rootfs referenced by root_fd.
*
* # Return Value
*
* On success, this function returns an O_DIRECTORY file descriptor to the
* newly created directory.
*
* If an error occurs, this function will return a negative error code. To
* retrieve information about the error (such as a string describing the error,
* the system errno(7) value associated with the error, etc), use
* pathrs_errorinfo().
*/
int pathrs_mkdir_all(int root_fd, const char *path, unsigned int mode);

/**
* Create a inode within the rootfs referenced by root_fd. The type of inode to
* be created is configured using the S_IFMT bits in mode (a-la mknod(2)).
Expand Down
21 changes: 21 additions & 0 deletions src/capi/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,27 @@ pub extern "C" fn pathrs_mkdir(root_fd: RawFd, path: *const c_char, mode: c_uint
pathrs_mknod(root_fd, path, libc::S_IFDIR | mode, 0)
}

/// Create a new directory (and any of its path components if they don't exist)
/// within the rootfs referenced by root_fd.
///
/// # Return Value
///
/// On success, this function returns an O_DIRECTORY file descriptor to the
/// newly created directory.
///
/// If an error occurs, this function will return a negative error code. To
/// retrieve information about the error (such as a string describing the error,
/// the system errno(7) value associated with the error, etc), use
/// pathrs_errorinfo().
#[no_mangle]
pub extern "C" fn pathrs_mkdir_all(root_fd: RawFd, path: *const c_char, mode: c_uint) -> RawFd {
ret::with_fd(root_fd, |root: &mut Root| {
let mode = mode & !libc::S_IFMT;
let perm = Permissions::from_mode(mode);
root.mkdir_all(utils::parse_path(path)?, &perm)
})
}

/// Create a inode within the rootfs referenced by root_fd. The type of inode to
/// be created is configured using the S_IFMT bits in mode (a-la mknod(2)).
///
Expand Down

0 comments on commit 0aeccc6

Please sign in to comment.