summaryrefslogtreecommitdiff
path: root/os.h
blob: 20135ffda2f78317b6d63fdd1929cb031b39ec98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// a bunch of OS-dependent functions
#ifndef OS_H_
#define OS_H_

#include "base.h"

typedef enum {
	FS_NON_EXISTENT,
	FS_FILE,
	FS_DIRECTORY,
	FS_OTHER
} FsType;

enum {
	FS_PERMISSION_READ = 0x01,
	FS_PERMISSION_WRITE = 0x02,
};
typedef u8 FsPermission;

typedef struct {
	FsType type;
	char name[];
} FsDirectoryEntry;

// returns what kind of thing this is.
FsType fs_path_type(const char *path);
FsPermission fs_path_permission(const char *path);
// Does this file exist? Returns false for directories.
bool fs_file_exists(const char *path);
// Returns a NULL-terminated array of the files/directories in this directory, or NULL if the directory does not exist/out of memory.
// When you're done with the entries, call fs_dir_entries_free (or call free on each entry, then on the whole array).
// NOTE: The files/directories aren't returned in any particular order!
FsDirectoryEntry **fs_list_directory(const char *dirname);
// Create the directory specified by `path`
// Returns:
// 1  if the directory was created successfully
// 0  if the directory already exists
// -1 if the path already exists, but it's not a directory, or if there's another error (e.g. don't have permission to create directory).
int fs_mkdir(const char *path);
// Puts the current working directory into buf, including a null-terminator, writing at most buflen bytes.
// Returns:
// 1  if the working directory was inserted into buf successfully
// 0  if buf is too short to hold the cwd
// -1 if we can't get the cwd for whatever reason.
int os_get_cwd(char *buf, size_t buflen);
struct timespec time_last_modified(const char *filename);
struct timespec time_get(void);
// sleep for a certain number of nanoseconds
void time_sleep_ns(u64 ns);


// free the entries generated by fs_list_directory.
static void fs_dir_entries_free(FsDirectoryEntry **entries) {
	for (int i = 0; entries[i]; ++i)
		free(entries[i]);
	free(entries);
}

static double time_get_seconds(void) {
	struct timespec t = time_get();
	return (double)t.tv_sec
		+ (double)t.tv_nsec * 1e-9;
}



// sleep for microseconds
static void time_sleep_us(u64 us) {
	time_sleep_ns(us * 1000);
}

// sleep for milliseconds
static void time_sleep_ms(u64 ms) {
	time_sleep_ns(ms * 1000000);
}

// sleep for seconds
static void time_sleep_s(u64 s) {
	time_sleep_ns(s * 1000000000);
}


typedef struct Process Process;

// zero everything except what you're using
typedef struct {
	bool stdin_blocking;
	bool stdout_blocking;
	bool separate_stderr;
	bool stderr_blocking; // not applicable if separate_stderr is false.
	const char *working_directory;
} ProcessSettings;

// get process ID of this process
int process_get_id(void);
// execute the given command (like if it was passed to system()), creating a new Process object.
// returns a valid process object on failure, but it will have an error, according to process_geterr
Process *process_run_ex(const char *command, const ProcessSettings *props);
// like process_run_ex, but with the default settings
Process *process_run(const char *command);
// returns the error last error produced, or NULL if there was no error.
const char *process_geterr(Process *process);
// write to stdin
// returns:
// -2 on error
// or a non-negative number indicating the number of bytes written.
// If stdin is set to blocking, fewer than `size` bytes will be written only if an error occured.
long long process_write(Process *process, const char *data, size_t size);
// read from stdout+stderr
// returns:
// -2 on error
// -1 if no data is available right now
// 0 on end of file
// or a positive number indicating the number of bytes read to data (at most size)
// If stdout is set to blocking, fewer than `size` bytes will be read only if an error occured or end-of-file was reached.
long long process_read(Process *process, char *data, size_t size);
// like process_read, but reads stderr.
// this function ALWAYS RETURNS -2 if separate_stderr is not specified in the ProcessSettings.
//   if separate_stderr is false, then both stdout and stderr will be sent via process_read.
long long process_read_stderr(Process *process, char *data, size_t size);
// Checks if the process has exited. Returns:
// -1 if the process returned a non-zero exit code, or got a signal.
// 1  if the process exited successfully
// 0  if the process hasn't exited.
// If message is not NULL, it will be set to a description of what happened (e.g. "exited successfully")
// if the process is no longer running, *process will be freed and set to NULL.
int process_check_status(Process **process, char *message, size_t message_size);
// kills process if still running
// this also frees any resources used by `*process`.
// *process will be set to NULL.
void process_kill(Process **process);

#endif // OS_H_