forked from urbit/vere
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfoil.c
147 lines (131 loc) · 3.24 KB
/
foil.c
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
135
136
137
138
139
140
141
142
143
144
145
146
147
/// @file
#include "noun.h"
#include "vere.h"
/* assumptions:
** all measurements are in chubs (double-words, c3_d, uint64_t).
** little-endian addressing is ASSUMED.
**
** framing:
** the last two chubs of a frame:
**
** {
** 64-bit frame length
** {
** (high 32 bits) mug of frame
** (low 32 bits) mug of current address
** }
** }
**
** we can scan for one of these frames with very low probability
** of a false positive. we always write to and read from the end
** of a file. a frame position points to its end.
**
** protocol:
** once the callback is called, all results are fully fsynced.
** all callbacks are optional and can be passed 0.
*/
/* _foil_fail(): fail with error.
*/
static void
_foil_fail(const c3_c* why_c, c3_i err_i)
{
if ( err_i ) {
u3l_log("%s: error: %s", why_c, uv_strerror(err_i));
u3_assert(0);
} else {
u3l_log("%s: file error", why_c);
}
exit(1);
}
/* _foil_close(): close file, blockingly.
*/
static void
_foil_close(uv_file fil_f)
{
c3_i err_i;
uv_fs_t ruq_u;
if ( 0 != (err_i = uv_fs_close(u3L, &ruq_u, fil_f, 0)) ) {
_foil_fail("uv_fs_close", err_i);
}
}
/* _foil_path(): allocate path.
*/
static c3_c*
_foil_path(u3_dire* dir_u,
const c3_c* nam_c)
{
c3_w len_w = strlen(dir_u->pax_c);
c3_c* pax_c;
pax_c = c3_malloc(1 + len_w + 1 + strlen(nam_c));
strcpy(pax_c, dir_u->pax_c);
pax_c[len_w] = '/';
strcpy(pax_c + len_w + 1, nam_c);
return pax_c;
}
/* u3_foil_folder(): load directory, blockingly. null if nonexistent.
*/
u3_dire*
u3_foil_folder(const c3_c* pax_c)
{
u3_dire* dir_u;
uv_fs_t ruq_u;
uv_dirent_t den_u;
c3_i err_i;
/* open directory, synchronously
*/
{
err_i = uv_fs_scandir(u3L, &ruq_u, pax_c, 0, 0);
if ( err_i < 0 ) {
if ( UV_ENOENT != err_i ) {
_foil_fail(pax_c, err_i);
return 0;
}
else {
if ( 0 != (err_i = uv_fs_mkdir(u3L, &ruq_u, pax_c, 0700, 0)) ) {
_foil_fail(pax_c, err_i);
return 0;
}
else {
uv_fs_req_cleanup(&ruq_u);
return u3_foil_folder(pax_c);
}
}
}
dir_u = u3_dire_init(pax_c);
}
/* create entries for all files and directories
*/
while ( UV_EOF != uv_fs_scandir_next(&ruq_u, &den_u) ) {
if ( UV_DIRENT_FILE == den_u.type ) {
u3_dent* det_u = u3_dent_init(den_u.name);
det_u->nex_u = dir_u->all_u;
dir_u->all_u = det_u;
} else if ( UV_DIRENT_DIR == den_u.type ) {
u3_dent* det_u = u3_dent_init(den_u.name);
det_u->nex_u = dir_u->dil_u;
dir_u->dil_u = det_u;
}
}
/* clean up request
*/
{
uv_fs_req_cleanup(&ruq_u);
}
/* open directory file for reading, to fsync
*/
{
if ( 0 > (err_i = uv_fs_open(u3L,
&ruq_u,
pax_c,
O_RDONLY,
0600,
0)) )
{
_foil_fail("open directory", err_i);
return 0;
}
dir_u->fil_u = ruq_u.result;
uv_fs_req_cleanup(&ruq_u);
}
return dir_u;
}