feat(unistd): cwd/link/readlink/path ops
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
#ifndef VLIBC_LIBGEN_H
|
||||
#define VLIBC_LIBGEN_H
|
||||
|
||||
/*
|
||||
* vlibc — <libgen.h>.
|
||||
*
|
||||
* basename() and dirname() split a pathname into its final component and
|
||||
* the directory that contains it (XSI, declared when _XOPEN_SOURCE is
|
||||
* enabled in glibc — level 2 here). They are the XSI forms: the input
|
||||
* path is modified in place (callers must pass a writable buffer), and
|
||||
* both are allowed to return pointers into a shared static area, so
|
||||
* repeated calls overwrite earlier results.
|
||||
*
|
||||
* The two functions are deliberately declared here and nowhere else:
|
||||
* POSIX places them in <libgen.h> only.
|
||||
*
|
||||
* Neither declaration carries an intent attribute: both functions write
|
||||
* to and return pointers into their argument or a shared static buffer,
|
||||
* so const/pure would be unsound.
|
||||
*/
|
||||
|
||||
#include <vlibc/features.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if VLIBC_LEVEL_GE(2)
|
||||
|
||||
/*
|
||||
* Return a pointer to the final component of path, modifying path in
|
||||
* place: trailing '/' characters (other than a leading root '/') are
|
||||
* overwritten with NUL so basename("/usr/lib") == "lib", basename("/")
|
||||
* == "/" and basename("") == ".". The result may be a suffix of path or
|
||||
* point into a shared static buffer (POSIX permits either); the special
|
||||
* cases "/" and "" return static strings.
|
||||
*/
|
||||
char *
|
||||
basename(char *path);
|
||||
|
||||
/*
|
||||
* Return a pointer to the directory portion of path, modifying path in
|
||||
* place: the last '/' that is not the final character is overwritten
|
||||
* with NUL so dirname("/usr/lib") == "/usr", dirname("/") == "/" and
|
||||
* dirname("") == ".". The result may be a suffix of path or point into
|
||||
* a shared static buffer (POSIX permits either); the special cases
|
||||
* return static strings.
|
||||
*/
|
||||
char *
|
||||
dirname(char *path);
|
||||
|
||||
#endif /* VLIBC_LEVEL_GE(2) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VLIBC_LIBGEN_H */
|
||||
+209
-1
@@ -31,7 +31,21 @@
|
||||
* configuration keys.
|
||||
* Level 2 (muslmimic): gethostname, sethostname, gethostid (XSI/BSD
|
||||
* system identification — NOT POSIX.1-2008 base),
|
||||
* and the _CS_* keys for todo 38's confstr().
|
||||
* and the _CS_* keys for confstr().
|
||||
*
|
||||
* The current-working-directory, link/symlink/readlink, path-removal and
|
||||
* *at operations, the terminal-identity and login functions, getopt and
|
||||
* confstr (todo 38) come after the system-limits block:
|
||||
*
|
||||
* Level 1 (onlyposix): getcwd, chdir, fchdir, readlink, symlink, link,
|
||||
* unlink, rmdir, linkat, readlinkat, renameat,
|
||||
* symlinkat, unlinkat, isatty, ttyname, ttyname_r,
|
||||
* getlogin, getlogin_r, getopt plus the optarg/
|
||||
* optind/opterr/optopt globals, and confstr (its
|
||||
* _CS_* key constants are level 2, above).
|
||||
* Level 2 (muslmimic): getwd (obsolescent), chroot, swab (XSI).
|
||||
* basename/dirname live in <libgen.h> and realpath
|
||||
* in <stdlib.h> (their POSIX homes), also XSI.
|
||||
*
|
||||
* uname() and struct utsname live in <sys/utsname.h> (todo 32).
|
||||
*
|
||||
@@ -474,9 +488,203 @@ pathconf(const char *path, int name);
|
||||
long
|
||||
fpathconf(int fildes, int name);
|
||||
|
||||
/* Level 1 (POSIX base): current directory, links, and path operations. */
|
||||
|
||||
/*
|
||||
* Store the absolute pathname of the current working directory into buf.
|
||||
* When buf is NULL, the path is returned in a malloc'd buffer instead
|
||||
* (size is then only a hint: 0 grows from a default of 128 bytes, and
|
||||
* the buffer is enlarged as the kernel reports ERANGE); the caller must
|
||||
* free it. Return buf (or the malloc'd buffer), or NULL with errno set
|
||||
* (EINVAL for a non-NULL buf with size 0).
|
||||
*/
|
||||
char *
|
||||
getcwd(char *buf, size_t size);
|
||||
|
||||
/*
|
||||
* Change the current working directory to path (chdir) or to the
|
||||
* directory referred to by the open descriptor fildes (fchdir). Return
|
||||
* 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
chdir(const char *path);
|
||||
|
||||
int
|
||||
fchdir(int fildes);
|
||||
|
||||
/*
|
||||
* Create a symbolic link: path2 is created as a link whose contents are
|
||||
* the string path1 (which need not exist). Return 0, or -1 with errno
|
||||
* set.
|
||||
*/
|
||||
int
|
||||
symlink(const char *path1, const char *path2);
|
||||
|
||||
/*
|
||||
* Like symlink(), but the link is created in the directory named by fd
|
||||
* when path2 is relative (use AT_FDCWD for the current working
|
||||
* directory). Return 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
symlinkat(const char *path1, int fd, const char *path2);
|
||||
|
||||
/*
|
||||
* Read the contents of the symbolic link path into buf (bufsize bytes,
|
||||
* no NUL is appended) and return the number of bytes placed in buf, 0
|
||||
* for an empty target, or -1 with errno set. The buffer is not
|
||||
* terminated: callers sized for bufsize + 1 append the NUL themselves.
|
||||
*/
|
||||
ssize_t
|
||||
readlink(const char *restrict path, char *restrict buf, size_t bufsize);
|
||||
|
||||
/*
|
||||
* Like readlink(), but path is resolved in the directory named by fd
|
||||
* when relative. Return the number of bytes placed in buf, or -1 with
|
||||
* errno set.
|
||||
*/
|
||||
ssize_t
|
||||
readlinkat(int fd, const char *restrict path, char *restrict buf, size_t bufsize);
|
||||
|
||||
/*
|
||||
* Create a hard link: new is created as a second name for the file old
|
||||
* (which must not be a directory and must be on the same filesystem).
|
||||
* Return 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
link(const char *old, const char *new);
|
||||
|
||||
/*
|
||||
* Like link(), but old and new are resolved against the directories
|
||||
* named by fd1 and fd2 when relative (AT_FDCWD selects the current
|
||||
* working directory) and flag may hold AT_SYMLINK_FOLLOW from <fcntl.h>.
|
||||
* Return 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
linkat(int fd1, const char *old, int fd2, const char *new, int flag);
|
||||
|
||||
/*
|
||||
* Remove the name path (a hard link; symbolic links are removed, not
|
||||
* followed). Return 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
unlink(const char *path);
|
||||
|
||||
/*
|
||||
* Like unlink(), but path is resolved in the directory named by fd when
|
||||
* relative and flag may hold AT_REMOVEDIR from <fcntl.h> (making it
|
||||
* remove an empty directory instead). Return 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
unlinkat(int fd, const char *path, int flag);
|
||||
|
||||
/*
|
||||
* Remove the empty directory path. Return 0, or -1 with errno set
|
||||
* (ENOTEMPTY/EEXIST when the directory is not empty).
|
||||
*/
|
||||
int
|
||||
rmdir(const char *path);
|
||||
|
||||
/*
|
||||
* Rename old to new within the filesystem: old is resolved against fd1
|
||||
* and new against fd2 (AT_FDCWD for the current working directory). Both
|
||||
* names may be directories. Return 0, or -1 with errno set.
|
||||
*/
|
||||
int
|
||||
renameat(int fd1, const char *old, int fd2, const char *new);
|
||||
|
||||
/* Level 1 (POSIX base): terminal identity, login name, getopt, confstr. */
|
||||
|
||||
/*
|
||||
* Test whether fildes refers to a terminal. Return 1 when it does, and
|
||||
* 0 otherwise (errno may be set — e.g. EBADF — but the caller must not
|
||||
* rely on it after a 0 return).
|
||||
*/
|
||||
int
|
||||
isatty(int fildes);
|
||||
|
||||
/*
|
||||
* Return the pathname of the terminal open on fildes in a shared static
|
||||
* buffer (overwritten by the next call), or NULL with errno set when
|
||||
* fildes is not a terminal. ttyname_r stores the path in the caller's
|
||||
* name buffer instead and returns 0, or an error NUMBER (ENOTTY when
|
||||
* fildes is not a terminal, ERANGE when the name does not fit in
|
||||
* namesize).
|
||||
*/
|
||||
char *
|
||||
ttyname(int fildes);
|
||||
|
||||
int
|
||||
ttyname_r(int fildes, char *name, size_t namesize);
|
||||
|
||||
/*
|
||||
* Return the login name of the user associated with the calling process
|
||||
* (the owner of its controlling terminal) in a shared static buffer, or
|
||||
* NULL with errno set when the name cannot be determined. getlogin_r
|
||||
* stores the name in the caller's buffer and returns 0, or an error
|
||||
* number (ERANGE when the name does not fit in namesize).
|
||||
*/
|
||||
char *
|
||||
getlogin(void);
|
||||
|
||||
int
|
||||
getlogin_r(char *name, size_t namesize);
|
||||
|
||||
/*
|
||||
* Command-line option parsing (POSIX.1-2008). getopt returns the next
|
||||
* option character from argv per the option characters in optstring; a
|
||||
* character followed by ':' in optstring takes an argument (delivered in
|
||||
* optarg). A leading ':' in optstring makes missing-argument errors
|
||||
* return ':' silently instead of '?' with a diagnostic to stderr.
|
||||
* Return -1 when all options have been consumed: optind then points at
|
||||
* the first non-option argument, and "--" terminates the scan.
|
||||
*/
|
||||
int
|
||||
getopt(int argc, char *const argv[], const char *optstring);
|
||||
|
||||
/* The getopt option state (POSIX.1-2008 base). */
|
||||
extern char *optarg; /* the argument of the option just returned */
|
||||
extern int optind; /* index of the next argument to scan (init 1) */
|
||||
extern int opterr; /* nonzero: write diagnostics to stderr (init 1) */
|
||||
extern int optopt; /* the option character that caused an error */
|
||||
|
||||
/*
|
||||
* Query the implementation-defined string value of configuration name
|
||||
* (one of the _CS_* keys above). When buf is not NULL and len is large
|
||||
* enough, the value (NUL-terminated) is copied into buf; the return
|
||||
* value is the length of the value including the terminating NUL, so a
|
||||
* return greater than len means the buffer was too small and nothing was
|
||||
* copied. For an unknown name, 0 is returned and errno is set to EINVAL.
|
||||
*/
|
||||
size_t
|
||||
confstr(int name, char *buf, size_t len);
|
||||
|
||||
#if VLIBC_LEVEL_GE(2)
|
||||
/* Level 2 (muslmimic): Linux extensions + XSI + obsolescent. */
|
||||
|
||||
/*
|
||||
* Store the current working directory into pathname, which must hold at
|
||||
* least PATH_MAX bytes. Return pathname, or NULL with errno set.
|
||||
* Obsolescent: prefer getcwd().
|
||||
*/
|
||||
char *
|
||||
getwd(char *pathname);
|
||||
|
||||
/*
|
||||
* Change the process root directory to path (used with chdir by
|
||||
* chroot-style confinement). Requires privilege. Return 0, or -1 with
|
||||
* errno set. XSI.
|
||||
*/
|
||||
int
|
||||
chroot(const char *path);
|
||||
|
||||
/*
|
||||
* Copy nbytes bytes from from to to, swapping each adjacent pair of
|
||||
* bytes (the odd byte of an odd count is not copied). Used for historic
|
||||
* byte-order conversion; returns nothing. XSI.
|
||||
*/
|
||||
void
|
||||
swab(const void *restrict from, void *restrict to, ssize_t nbytes);
|
||||
|
||||
/*
|
||||
* Like dup2(), but with descriptor flags (O_CLOEXEC from <fcntl.h>) applied
|
||||
* atomically; return fildes2, or -1 with errno set. Linux-specific.
|
||||
|
||||
Reference in New Issue
Block a user