Differences From
Artifact [194f78820a]:
1 1 # kfile
2 +kfile is libk's file handling library. kfile uses the short naming convention and its sigil is `f`. it is designed to abstract over OS idioms so that developers can write code that simply expresses their intent, and kfile will figure out the correct thing to do on a given platform. to that end, one of kfile's most important functions is `kfplace()` - see below.
3 +
4 +## functions
5 +
6 + * `struct kfile kfplace(enum kfplace location, const char* file, enum kfopen mode)` - when you need to open a file in a location that will vary between environments, such as configuration directories, download dirs, image dirs, etc, use `kfplace()` instead of `kfopen()`. the arguments work like `kfopen()`, except that `file` is not a normal path. instead, it specifies a file in the program's configuration directory to open, and the lead constant will tell it what kind of file you are trying to open. in most cases, a null or empty filename is an error, but see `enum kfplace` for exceptions. `file` must not begin with a slash; if they do, `kfcond_bad_domain` will be returned.
7 + * `kfcond kfget(enum kfplace, ksmut buffer)` - this function will write the prefix for a particular environment directory into `buffer`, or return `kfcond_fail` if `buffer` is not big enough. the best way to use this function is with a for loop; see examples. do not use this to generate paths for file access; use `kfplace()` instead.
8 + * `struct kfile kfopen(const char* file, enum kfopen mode)` - opens a file at the specified pathname. mode is a bit mask . if null is passed as a filename, a temporary file will be created in the appropriate place, using memfds or similar if available and the system temporary directory otherwise. `mode` is a bit flag; the lowest nine bits represent filesystem permissions to be used when creating a file and the rest control how the file will be opened - at least one of `kf_read` or `kf_write` must be passed. see `enum kfopen`. **do not** use kfopen to attempt direct access to configuration files in root of the user's home directory; libk **will** detect this and instruct your users to file bug reports. use kfplace(kfplace_conf) instead to open files in the configuration directory appropriate to the local environment.
9 + * `struct kfile kfopens(const ksraw file, enum kfopen mode)` - like kfopen but allows specifying the filename via a `ksraw` string rather than a `const char*`.
10 + * `kfcond kfset(struct kfile file, enum kfset_mode mode, sz position)` - repositions the read/write head at `position` bytes into the file (if mode is `kfset_top`) or at `position` bytes from the end of the file (if mode is `kfset_end`). attempting to index past the end of the file will return `kfcond_bad_index`. returns `kfcond_ok` on success.
11 + * `kfcond kfstep(struct kfile file, offset position)` - moves the read/write head `position` bytes ahead if `position` is a positive number, or backwards otherwise. attempting to move past the start or end of the file will move the cursor to the start or end and return `kfcond_overstep`. returns `kfcond_ok` on success.
12 + * `kfcond kfshred(struct kfile file, sz count)` - write over `file` with random data `count` times, then truncate it.
13 + * **posix functions** - POSIX has a wide array of nonportable file IO calls that are important particularly with regards to `exec()` and piping data across processes. for this reason, on POSIX platforms, libk exposes these calls to the user.
14 + * kfposix_pipe() - creates a pipe in memory
15 + * kfposix_fifo() - creates a named pipe at the specified path
16 +
17 +## structs
18 + * `struct kfile` - represents an open file. a `kfile` struct should always be initialized with `kfopen()` or `kfconf()` before use, or the values it contains will be meaningless and useless!
19 + * `enum kfile_kind kind` - either `kfile_closed` if the object does not represent an open file, or `kfile_open` if it does
20 + * `enum kfopen mode` - details about the open file. `kf_new` is only set if the file was created by a `kf_new`-flagged open call
21 + * `struct kiochan chan` - a channel that can be used to read or write to a file
22 + * `u8* content` - a pointer to the start of the file in memory, if it is loaded with `kf_map`
23 + * `sz len` - size of the file as of open. this is not updated by `kiosend()` calls!
24 +
25 +## enums
26 +
27 +### enum kfplace
28 +`enum kfplace` contains constants that refer to standardized locations that may vary across environments. on POSIX, the XDG specification will be respected to allow the user to select her own directories. unlike `kfopen()`, `kfplace()` will also create any necessary directories if `kf_new` or `kf_create` are passed.
29 +
30 + * `kfplace_conf` - this mode is designed specifically for opening configuration files. the configuration directory is determined based on OS, environment variables, and the name of the binary; on POSIX OSes, it will use `$XDG_CONFIG_HOME/argv[0]` as the configuration base, cleanly falling back to platform defaults (`$HOME/.config`, and determining home directories based on $USER or failing that UID if `$HOME` is unset). on OSX, it will use `~/Library/argv[0]`. note that if `null` or the empty string are passed as `file`, `kfconf()` will open a file with the name of the configuration base, instead of treating it as a folder to look for configuration files in.
31 + * `kfplace_home` - open a file in the user's home folder. on POSIX, it will use the value of `$HOME` or get the user's home directory with the appropriate calls if `$HOME` is unset. **THINK CAREFULLY BEFORE USING THIS FUNCTIONALITY - NEVER USE IT FOR STORING CONFIGURATION.** if you use this flag to create dotfiles in the homedir, libk **will** inform the user and instruct her to file a bug report.
32 + * `kfplace_desk` - open a file on the user's desktop, or failing that, home folder. on POSIX, it will use the value of `XDG_DESKTOP_DIR` in `$XDG_CONFIG_HOME/user-dirs.dirs`; on OSX, it will use `$HOME/Downloads`. the same restriction against dotfiles applies here as well.
33 + * `kfplace_dl` - open a file in the user's download directory. on POSIX, it will use the value of `XDG_DOWNLOAD_DIR` in `$XDG_CONFIG_HOME/user-dirs.dirs`; on OSX, it will use `$HOME/Downloads`.
34 + * `kfplace_img` - open a file in the user's image directory. on POSIX, it will use the value of `XDG_PICTURES_DIR` in `$XDG_CONFIG_HOME/user-dirs.dirs`; on OSX, it will use `$HOME/Pictures`.
35 + * `kfplace_vid` - open a file in the user's video directory. on POSIX, it will use the value of `XDG_VIDEOS_DIR` in `$XDG_CONFIG_HOME/user-dirs.dirs`; on OSX, it will use `$HOME/Movies`.
36 + * `kfplace_msc` - open a file in the user's video directory. on POSIX, it will use the value of `XDG_MUSIC_DIR` in `$XDG_CONFIG_HOME/user-dirs.dirs`; on OSX, it will use `$HOME/Music`.
37 + * `kfplace_dat` - open a file in the user data directory, the homedir equivalent of `/usr/share`. on POSIX, it will use the value of `$XDG_DATA_HOME/argv[0]`; on OSX, it will use `$HOME/Library/Application Support/argv[0]`.
38 + * `kfplace_share` - open a file in the system data directory. this is typified by `/usr/share/argv[0]` on POSIX. on OSX, it will use `/Library/Application Support/argv[0]`.
39 + * `kfplace_share_global` - like `kfplace_share`, except without the program-specific suffix.
40 + * `kfplace_cache` - open a file in the user's cache directory. on POSIX, this will generally be `$HOME/.cache/argv[0]`.
41 +
42 +### enum kfopen
43 +`enum kfopen` contains flags that may be OR'd together and passed to `kfopen()` to alter its behavior.
44 + * `kf_read` - opens a file for reading
45 + * `kf_write` - opens a file for writing
46 + * `kf_ascii` - opens a file in ascii mode, where available. if not set, the file will be opened in binary mode.
47 + * `kf_new` - creates a new file with the chosen name if one does not already exist, opening the existing file otherwise
48 + * `kf_create` - creates a new file with the chosen name if it does not already exist, failing otherwise
49 + * `kf_load` - loads the file directly into memory, allowing it to be read via indexing into a pointer rather than kiosend() and kiorecv() calls. this is most useful for quickly opening files for reading. if kf_write is also passed, a kiochan will be created to permit writing to the file via standard mechanisms. note: `kf_load` will use mmap() to load the file where possible, but on systems without `mmap()` or `MMAP_SHARED`, `kf_load` will be implemented using standard file IO primitives. for this reason, writing to the region of memory containing the file is implementation-defined behavior. if you really want to be able to modify the file in memory, use `kf_map` instead - it is guaranteed to memory-map the file, but will fail outright on platforms without memory mapping available, so its use is discouraged unless absolutely necessary, or as a platform-specific optimization.
50 + * `kf_top` - if passed, the kiochan will be positioned at the top of the file. this is the default if kf_read is passed; otherwise, it will be positioned at the end so the file can be appended to.
51 + * if you wish to read the file with kiorecv() calls: `kf_read | kf_top`
52 + * if you wish your writes to overwrite what is already present in the file: `kf_write | kf_top`
53 + * if you wish to append to an existing file: `kf_write | kf_end`
54 + * `kf_end` - positions the `kiochan` at the end of the file. see above.
55 + * `kf_wipe` - if a file already exists, erase its contents before writing. to prevent accidental deletions, it is an error to pass `kf_read | kf_wipe`.
56 + * kfopen also has constants that can be used to spell out file permissions; these are guaranteed to be the standard POSIX octal triple on all platforms. on POSIX platforms, the triple will be passed through to the OS unmodified; on others, libk itself will interpret it.
57 + * `kf_ur` - represents the owner's permission to read the file
58 + * `kf_uw` - represents the owner's permission to write to the file
59 + * `kf_ux` - represents the owner's permission to execute the file
60 + * `kf_gr` - represents the group's permission to read the file
61 + * `kf_gw` - represents the group's permission to write to the file
62 + * `kf_gx` - represents the group's permission to execute the file
63 + * `kf_or` - represents all other users' permission to read the file
64 + * `kf_ow` - represents all other users' permission to write to the file
65 + * `kf_ox` - represents all other users' permission to execute the file
66 +
67 +## macros
68 +if `KFclean` is not defined, the following macros will be:
69 +
70 + * `KFsep` is the string used to separate directories in file paths. it will be set to `"\\"` on Windows, `"/"` on POSIX, and so on.
71 +
72 +## examples
73 +`kfget()` is somewhat tricky to use. this is a feature, not a bug - there are very few legitimate uses for it and it should not be convenient to use. use `kfplace()` instead.
74 +
75 + for (sz len = 80; len < kf_path_max; len << 2) {
76 + char path [len];
77 + if (kfget(kfplace_desk, (ksmut){len, path}) != kfcond_ok)
78 + continue;
79 + kiosend(env.std, (ksraw){len, path}, null);
80 + break;
81 + }