|
PatchworkOS
c9fea19
A non-POSIX operating system.
|
Unique location in the filesystem. More...
Unique location in the filesystem.
A path is a single unique location in the filesystem hierarchy. It consists of a mount and a dentry. The mount is the filesystem that the path is in and the dentry is the actual location in that filesystem.
Note how just a dentry is not enough to uniquely identify a location in the filesystem, this is because of mountpoints. A dentry can exist in a filesystem that is mounted at multiple locations in the filesystem hierarchy, thus both a mountpoint and a dentry is needed to uniquely identify a location.
Paths can have flags appended at the end, these flags are parsed to determine the mode with which the path is opened.
Each flag starts with : and multiple instances of the same flag are allowed, for example /path/to/file:append:append:nonblock.
Included is a list of all available flags:
| Flag | Short | Description |
|---|---|---|
read | r | Open with read permissions. |
write | w | Open with write permissions. |
execute | x | Open with execute permissions. |
nonblock | n | The file will not block on operations that would normally block. |
append | a | Any data written to the file will be appended to the end. |
create | c | Create the file if it does not exist. |
exclusive | e | Will cause the open to fail if the file already exists. |
truncate | t | Truncate the file to zero length if it already exists. |
directory | d | Allow opening directories. |
recursive | R | Behaviour differs, but allows for recursive operations, for example when used with remove it |
will remove directories and their children recursively. |
For convenience, a single letter short form is also available as shown above, these single letter forms do not need to be separated by colons, for example /path/to/file:rwcte is equivalent to /path/to/file:read:write:create:truncate:exclusive.
The parsed mode is the primary way to handle both the behaviour of opened paths and permissions through out the kernel. For example, a file opened from within a directory which was bound with only read permissions will also have read only permissions, even if the file itself would allow write permissions.
If no permissions, i.e. read, write or execute, are specified, the default is to open with the maximum currently allowed permissions.
Data Structures | |
| struct | path_t |
| Path structure. More... | |
| struct | pathname_t |
| Pathname structure. More... | |
Macros | |
| #define | PATH_DEFER(path) __attribute__((cleanup(path_defer_cleanup))) path_t* CONCAT(i, __COUNTER__) = (path) |
| Defer path put. | |
| #define | PATH_VALID_CHAR(ch) (strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-. ()[]{}~!@#$%^&?',;=+", (ch))) |
| Check if a char is valid. | |
| #define | PATH_HANDLE_DOTDOT_MAX_ITER 1000 |
Maximum iterations to handle .. in a path. | |
| #define | PATHNAME_IS_VALID(pathname) ((pathname) != NULL && (pathname)->isValid) |
| Check if a pathname is valid. | |
| #define | PATHNAME(string) |
| Helper to create a pathname. | |
| #define | PATH_EMPTY |
| Helper to create an empty path. | |
| #define | PATH_CREATE(inMount, inDentry) |
| Helper to create a path. | |
Enumerations | |
| enum | mode_t { MODE_NONE = 0 , MODE_READ = 1 << 0 , MODE_WRITE = 1 << 1 , MODE_EXECUTE = 1 << 2 , MODE_NONBLOCK = 1 << 3 , MODE_APPEND = 1 << 4 , MODE_CREATE = 1 << 5 , MODE_EXCLUSIVE = 1 << 6 , MODE_TRUNCATE = 1 << 7 , MODE_DIRECTORY = 1 << 8 , MODE_RECURSIVE = 1 << 9 , MODE_AMOUNT = 10 , MODE_ALL_PERMS = MODE_READ | MODE_WRITE | MODE_EXECUTE } |
| Path flags and permissions. More... | |
Functions | |
| uint64_t | pathname_init (pathname_t *pathname, const char *string) |
| Initialize a pathname. | |
| void | path_set (path_t *path, mount_t *mount, dentry_t *dentry) |
| Set a path. | |
| void | path_copy (path_t *dest, const path_t *src) |
| Copy a path. | |
| void | path_put (path_t *path) |
| Put a path. | |
| uint64_t | path_step (path_t *path, const char *name, namespace_t *ns) |
| Walk a single step in a path. | |
| uint64_t | path_walk (path_t *path, const pathname_t *pathname, namespace_t *ns) |
| Walk a pathname to a path. | |
| uint64_t | path_walk_parent (path_t *path, const pathname_t *pathname, char *outLastName, namespace_t *ns) |
| Walk a pathname to its parent and get the name of the last component. | |
| uint64_t | path_walk_parent_and_child (const path_t *from, path_t *outParent, path_t *outChild, const pathname_t *pathname, namespace_t *ns) |
| Traverse a pathname to its parent and child paths. | |
| uint64_t | path_to_name (const path_t *path, pathname_t *pathname) |
| Convert a path to a pathname. | |
| static void | path_defer_cleanup (path_t **path) |
| #define PATH_DEFER | ( | path | ) | __attribute__((cleanup(path_defer_cleanup))) path_t* CONCAT(i, __COUNTER__) = (path) |
Defer path put.
This macro will call path_put() on the given path when it goes out of scope.
| path | The path to defer. |
| #define PATH_VALID_CHAR | ( | ch | ) | (strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-. ()[]{}~!@#$%^&?',;=+", (ch))) |
Check if a char is valid.
A valid char is one of the following ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-. ()[]{}~!#$%^&?’,;=+`.
| ch | The char to check. |
| #define PATH_HANDLE_DOTDOT_MAX_ITER 1000 |
| #define PATHNAME_IS_VALID | ( | pathname | ) | ((pathname) != NULL && (pathname)->isValid) |
Check if a pathname is valid.
A valid pathname is not NULL and has its isValid flag set to true.
This flag is set in pathname_init().
| pathname | The pathname to check. |
| #define PATHNAME | ( | string | ) |
Helper to create a pathname.
This macro will create a pathname on the stack and initialize it with the given string.
This is also the reason we have the isValid flag in the pathname_t structure, to be able to check if this macro failed without having to return an error code, streamlining the code a bit.
| string | The string to initialize the pathname with. |
| #define PATH_EMPTY |
Helper to create an empty path.
Its important to always use this as some functions, for example path_copy(), will deref the existing mount and dentry in the path.
| #define PATH_CREATE | ( | inMount, | |
| inDentry | |||
| ) |
Helper to create a path.
| inMount | The mount of the path. |
| inDentry | The dentry of the path. |
| enum mode_t |
Path flags and permissions.
We store both flags and permissions in the same enum but permissions are sometimes treated differently to flags.
| Enumerator | |
|---|---|
| MODE_NONE | |
| MODE_READ | |
| MODE_WRITE | |
| MODE_EXECUTE | |
| MODE_NONBLOCK | |
| MODE_APPEND | |
| MODE_CREATE | |
| MODE_EXCLUSIVE | |
| MODE_TRUNCATE | |
| MODE_DIRECTORY | |
| MODE_RECURSIVE | |
| MODE_AMOUNT | |
| MODE_ALL_PERMS | |
| uint64_t pathname_init | ( | pathname_t * | pathname, |
| const char * | string | ||
| ) |
Initialize a pathname.
If the string is invalid, it will error and set pathname->isValid to false.
| pathname | The pathname to initialize. |
| string | The string to initialize the pathname with. |
0. On failure, ERR and errno is set to:EINVAL: Invalid parameters.ENAMETOOLONG: The string is too long or a component name is too long. Definition at line 89 of file path.c.
| void path_put | ( | path_t * | path | ) |
| uint64_t path_step | ( | path_t * | path, |
| const char * | name, | ||
| namespace_t * | ns | ||
| ) |
Walk a single step in a path.
| path | The path to traverse, will be updated to the new path, may be negative. |
| name | The name of the child dentry. |
| ns | The namespace to access mountpoints. |
0. On failure, ERR and errno is set. Definition at line 323 of file path.c.
| uint64_t path_walk | ( | path_t * | path, |
| const pathname_t * | pathname, | ||
| namespace_t * | ns | ||
| ) |
Walk a pathname to a path.
| path | The path to start from, will be updated to the new path, may be negative. |
| pathname | The pathname to walk to. |
| ns | The namespace to access mountpoints. |
0. On failure, ERR and errno is set. Definition at line 347 of file path.c.
| uint64_t path_walk_parent | ( | path_t * | path, |
| const pathname_t * | pathname, | ||
| char * | outLastName, | ||
| namespace_t * | ns | ||
| ) |
Walk a pathname to its parent and get the name of the last component.
Will not modify outParent and outChild on failure.
| path | The path to start from, will be updated to the parent path. |
| pathname | The pathname to traverse. |
| outLastName | The output last component name, must be at least MAX_NAME bytes. |
| ns | The namespace to access mountpoints. |
0. On failure, ERR and errno is set. Definition at line 440 of file path.c.
| uint64_t path_walk_parent_and_child | ( | const path_t * | from, |
| path_t * | outParent, | ||
| path_t * | outChild, | ||
| const pathname_t * | pathname, | ||
| namespace_t * | ns | ||
| ) |
Traverse a pathname to its parent and child paths.
Will not modify outParent and outChild on failure.
| from | The path to start from. |
| outParent | The output parent path. |
| outChild | The output child path, may be negative. |
| pathname | The pathname to traverse. |
| ns | The namespace to access mountpoints. |
0. On failure, ERR and errno is set. Definition at line 497 of file path.c.
| uint64_t path_to_name | ( | const path_t * | path, |
| pathname_t * | pathname | ||
| ) |
Convert a path to a pathname.
The resulting pathname will be absolute.
| path | The path to convert. |
| pathname | The output pathname. |
0. On failure, ERR and errno is set. Definition at line 522 of file path.c.