2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
29 private fn unsafe_get_world : world;
30 fn recover_world(w old_w : world) : world;
31 fn join(t : type, w1 w2 : t) : t;
32 fn any~lazy(t1 t2 : type, w1 : t1, w2 : t2) : bool;
33 fn any_list~lazy(t : type, wx : list(t)) : int;
34 fn is_ready(t : type, v : t) : bool;
35 fn never(t : type) : t;
36 fn fork(t : type, w : t) : (t, t);
37 fn atomic_enter~inline(w : world) : world;
38 fn atomic_exit~inline(w : world) : world;
39 fn exit(w : world, n : int) : world;
40 fn exit_msg(w : world, n : int, m : bytes) : world;
46 private fn get_args(w : world) : list(bytes);
55 const open_flag_read : int;
56 const open_flag_write : int;
57 const open_flag_append : int;
58 const open_flag_create : int;
59 const open_flag_must_create : int;
60 const open_flag_no_follow : int;
61 const open_mode_ro_current_user : int;
62 const open_mode_ro_all_users : int;
63 const open_mode_rw_current_user : int;
64 const open_mode_read_all_users : int;
65 const open_mode_default : int;
67 fn ropen(w : world, d : dhandle, f : bytes, flags : int) : (world, handle);
68 fn read(w : world, h : handle, size : int) : (world, bytes);
69 fn read_partial(w : world, h : handle, size : int) : (world, bytes);
70 fn wopen(w : world, d : dhandle, f : bytes, flags : int, mode : int) : (world, handle);
71 fn write(w : world, h : handle, s : bytes) : world;
72 fn wcontiguous(w : world, h : handle, size : int64) : world;
74 fn ropen_lazy(d : dhandle, f : bytes, flags : int) : handle;
75 fn read_lazy~lazy(r : handle) : bytes;
77 private fn read_console_packet(w : world, h : handle) : (world, list(int32));
78 private fn write_console_packet(w : world, h : handle, cp : list(int32)) : world;
80 fn pipe(w : world) : (world, handle, handle);
82 fn bopen(w : world, d : dhandle, f : bytes, flags : int, mode : int) : (world, handle);
83 fn bread(w : world, h : handle, position : int64, size : int) : (world, bytes);
84 fn bwrite(w : world, h : handle, position : int64, s : bytes) : world;
85 fn bsize(w : world, h : handle) : (world, int64);
86 fn bdata(w : world, h : handle, off : int64) : (world, int64);
87 fn bhole(w : world, h : handle, off : int64) : (world, int64);
88 fn bsetsize(w : world, h : handle, size : int64) : world;
89 fn bcontiguous(w : world, h : handle, pos : int64, size : int64) : world;
90 fn bclone(w : world, src_h : handle, src_pos : int64, dst_h : handle, dst_pos : int64, size : int64) : world;
91 fn bopen_lazy(d : dhandle, f : bytes, flags : int) : handle;
92 fn bread_lazy~lazy(h : handle, position : int64) : bytes;
93 fn bsize_lazy(h : handle) : int64;
94 fn bdata_lazy(h : handle, off : int64) : int64;
95 fn bhole_lazy(h : handle, off : int64) : int64;
97 fn fdatasync(w : world, h : handle) : world;
98 fn fsync(w : world, h : handle) : world;
99 fn ffssync(w : world, h : handle) : world;
100 fn sync(w : world) : world;
102 fn droot(w : world) : dhandle;
103 private fn dcwd(w : world) : dhandle;
104 private fn dlib(w : world) : dhandle;
105 private fn dexe(w : world) : dhandle;
106 fn dnone(w : world) : dhandle;
107 private fn libpath : bytes;
108 fn dopen(w : world, d : dhandle, f : bytes, flags : int) : (world, dhandle);
109 fn dread(w : world, d : dhandle) : (world, list(bytes));
110 fn dpath(w : world, d : dhandle) : (world, bytes);
111 fn dopen_lazy(d : dhandle, f : bytes, flags : int) : dhandle;
112 fn dread_lazy(d : dhandle) : list(bytes);
113 fn dpath_lazy(d : dhandle) : bytes;
114 fn dmonitor(w : world, d : dhandle) : (world, world);
116 const stat_flag_devmajor : int;
117 const stat_flag_devminor : int;
118 const stat_flag_inode : int;
119 const stat_flag_type : int;
120 const stat_flag_mode : int;
121 const stat_flag_nlink : int;
122 const stat_flag_uid : int;
123 const stat_flag_gid : int;
124 const stat_flag_rdevmajor : int;
125 const stat_flag_rdevminor : int;
126 const stat_flag_size : int;
127 const stat_flag_optimaliosize : int;
128 const stat_flag_allocated : int;
129 const stat_flag_atime : int;
130 const stat_flag_mtime : int;
131 const stat_flag_ctime : int;
133 const stat_type_file : int;
134 const stat_type_directory : int;
135 const stat_type_link : int;
136 const stat_type_fifo : int;
137 const stat_type_chardev : int;
138 const stat_type_blockdev : int;
139 const stat_type_socket : int;
141 fn stat(w : world, d : dhandle, f : bytes, flags : int) : (world, list(int64));
142 fn lstat(w : world, d : dhandle, f : bytes, flags : int) : (world, list(int64));
143 fn fstat(w : world, h : handle, flags : int) : (world, list(int64));
145 fn stat_lazy(d : dhandle, f : bytes, flags : int) : list(int64);
146 fn lstat_lazy(d : dhandle, f : bytes, flags : int) : list(int64);
147 fn fstat_lazy(h : handle, flags : int) : list(int64);
149 const statfs_flag_bsize : int;
150 const statfs_flag_frsize : int;
151 const statfs_flag_frtotal : int;
152 const statfs_flag_frfree : int;
153 const statfs_flag_fravail : int;
154 const statfs_flag_intotal : int;
155 const statfs_flag_infree : int;
156 const statfs_flag_inavail : int;
157 const statfs_flag_fsid : int;
158 const statfs_flag_flags : int;
159 const statfs_flag_namelen : int;
161 const statfs_st_readonly : int;
162 const statfs_st_nosuid : int;
163 const statfs_st_nodev : int;
164 const statfs_st_noexec : int;
165 const statfs_st_synchronous : int;
166 const statfs_st_mandlock : int;
167 const statfs_st_noatime : int;
168 const statfs_st_nodiratime : int;
169 const statfs_st_relatime : int;
171 fn fstatfs(w : world, h : handle, flags : int) : (world, list(int64));
172 fn dstatfs(w : world, d : dhandle, flags : int) : (world, list(int64));
174 fn readlink(w : world, d : dhandle, f : bytes) : (world, bytes);
175 fn readlink_lazy(d : dhandle, f : bytes) : bytes;
177 fn unlink(w : world, d : dhandle, f : bytes) : world;
178 fn rmdir(w : world, d : dhandle, f : bytes) : world;
179 fn mkdir(w : world, d : dhandle, f : bytes, mode : int) : world;
180 fn mkpipe(w : world, d : dhandle, f : bytes, mode : int) : world;
181 fn mksocket(w : world, d : dhandle, f : bytes, mode : int) : world;
182 fn mkchardev(w : world, d : dhandle, f : bytes, mode major minor : int) : world;
183 fn mkblockdev(w : world, d : dhandle, f : bytes, mode major minor : int) : world;
184 fn mksymlink(w : world, d : dhandle, f t : bytes) : world;
185 fn mklink(w : world, d : dhandle, f : bytes, e : dhandle, t : bytes) : world;
186 fn rename(w : world, d : dhandle, f : bytes, e : dhandle, t : bytes) : world;
187 fn chmod(w : world, d : dhandle, f : bytes, m : int) : world;
188 fn chown(w : world, d : dhandle, f : bytes, uid gid : int) : world;
189 fn lchown(w : world, d : dhandle, f : bytes, uid gid : int) : world;
190 fn utime(w : world, d : dhandle, f : bytes, atime mtime : int64) : world;
191 fn lutime(w : world, d : dhandle, f : bytes, atime mtime : int64) : world;
193 const stty_flag_raw : int;
194 const stty_flag_noecho : int;
195 const stty_flag_nosignal : int;
196 const stty_flag_nocrlf : int;
198 fn stty(w : world, h : handle, flags : int) : world;
199 fn tty_size(w : world, h : handle, x y : int) : (world, int, int);
201 const uname_flag_ajla_version : int;
202 const uname_flag_flavor : int;
203 const uname_flag_system : int;
204 const uname_flag_release : int;
205 const uname_flag_version : int;
206 const uname_flag_machine : int;
208 fn uname(flags : int) : list(bytes);
209 fn get_host_name(w : world) : (world, bytes);
211 fn get_real_time(w : world) : (world, int64);
212 fn get_monotonic_time(w : world) : (world, int64);
213 fn sleep(t : type, w : t, tm : int64) : t;
219 const path_separator : byte;
220 fn path_is_separator(b : byte) : bool;
221 fn path_is_dir_separator(b : byte) : bool;
222 fn path_compare(a b : bytes) : bool;
223 fn path_is_absolute(p : bytes) : bool;
224 fn path_is_root(p : bytes) : bool;
225 fn path_to_dir_file(p : bytes) : (bytes, bytes);
226 fn path_append(pd pf : bytes) : bytes;
227 fn path_contract(p : bytes) : bytes;
228 fn path_join(pd pf : bytes) : bytes;
229 fn path_canonical(w : world, d : dhandle, p : bytes) : (world, bytes);
230 fn path_get_cwd(implicit w : world, d : dhandle, env : treemap(bytes, bytes)) : (world, bytes);
231 fn path_shortcut_home(home : maybe(bytes), p : bytes) : bytes;
232 fn path_expand_home(home : maybe(bytes), p : bytes) : bytes;
233 fn path_mkdir(w : world, d : dhandle, f : bytes, mode : int) : world;
234 fn path_xdg(implicit w : world, env : treemap(bytes, bytes), xdg_env : bytes, deflt : bytes, appname : bytes) : (world, dhandle);
235 fn path_config(w : world, env : treemap(bytes, bytes), appname : bytes) : (world, dhandle);
236 fn path_write_atomic(w : world, d : dhandle, f : bytes, content : bytes) : world;
242 fn register_dependence(w : world, d : dhandle, p : bytes) : world;
258 fn unsafe_get_world : world
263 fn recover_world(w old_w : world) : world
265 if is_exception w then
270 fn join(t : type, w1 w2 : t) : t
272 if is_exception w1 then [
276 if is_exception w2 then
281 fn any~lazy(t1 t2 : type, w1 : t1, w2 : t2) : bool
284 pcode IO IO_Any 1 2 0 =b w1 w2;
288 fn any_list~lazy(t : type, wx : list(t)) : int
290 if not len_greater_than(wx, 0) then
292 var n := any_list~lazy(wx[1 .. ]);
293 var b := any(wx[0], n);
294 return select(b, 0, n + 1);
297 fn is_ready(t : type, v : t) : bool
299 return not any(v, unit_value);
302 fn never(t : type) : t
305 pcode IO IO_Never 1 0 0 =w;
309 fn fork(t : type, w : t) : (t, t)
312 pcode IO IO_Fork 2 1 0 =w1 =w2 w;
316 fn atomic_enter~inline(w : world) : world
319 pcode IO IO_Atomic_Enter 1 1 0 =w2 w;
323 fn atomic_exit~inline(w : world) : world
326 pcode IO IO_Atomic_Exit 1 1 0 =w2 w;
330 fn exit(w : world, n : int) : world
332 var exc := exception_make(world, ec_exit, error_exit, n, false);
336 fn exit_msg(w : world, n : int, m : bytes) : world
338 var exc := exception_make_str(world, ec_exit, error_exit, n, false, m);
346 fn get_args(w : world) : list(bytes)
349 pcode IO IO_Get_Args 1 1 0 =r w;
357 type handle := internal_type;
358 type dhandle := internal_type;
360 const open_flag_read : int := IO_Open_Flag_Read;
361 const open_flag_write : int := IO_Open_Flag_Write;
362 const open_flag_append : int := IO_Open_Flag_Append;
363 const open_flag_create : int := IO_Open_Flag_Create;
364 const open_flag_must_create : int := IO_Open_Flag_Must_Create;
365 const open_flag_no_follow : int := IO_Open_Flag_No_Follow;
366 const open_mode_ro_current_user : int := #100;
367 const open_mode_ro_all_users : int := #124;
368 const open_mode_rw_current_user : int := #180;
369 const open_mode_read_all_users : int := #1a4;
370 const open_mode_default : int := #1b6;
372 fn ropen(w : world, d : dhandle, f : bytes, flags : int) : (world, handle)
377 pcode IO IO_Stream_Open_Read 2 5 0 =w2 =h w d f flags mode;
381 fn read(w : world, h : handle, size : int) : (world, bytes)
383 var read_so_far := 0;
385 while read_so_far < size do [
388 w2, s1 := read_partial~strict(w, h, size - read_so_far);
399 fn read_partial(w : world, h : handle, size : int) : (world, bytes)
403 pcode IO IO_Stream_Read_Partial 2 3 0 =w2 =s w h size;
407 fn wopen(w : world, d : dhandle, f : bytes, flags : int, mode : int) : (world, handle)
411 pcode IO IO_Stream_Open_Write 2 5 0 =w2 =h w d f flags mode;
415 fn write(w : world, h : handle, s : bytes) : world
417 while len_greater_than(byte, s, 0) do [
420 pcode IO IO_Stream_Write 2 3 0 =w2 =sz w h s;
427 fn wcontiguous(implicit w : world, h : handle, size : int64) : world
429 var offset := bsize(h);
430 bcontiguous(w, h, offset, size);
433 fn ropen_lazy(d : dhandle, f : bytes, flags : int) : handle
436 var w := unsafe_get_world;
437 w, h := ropen(w, d, f, flags);
441 fn read_lazy~lazy(r : handle) : bytes
444 var w := unsafe_get_world;
445 w, b := read_partial~strict(w, r, 16384);
448 return b + read_lazy(r);
451 fn read_console_packet(w : world, h : handle) : (world, list(int32))
453 var cp : list(int32);
455 pcode IO IO_Read_Console_Packet 2 2 0 =w2 =cp w h;
459 fn write_console_packet(w : world, h : handle, cp : list(int32)) : world
462 pcode IO IO_Write_Console_Packet 1 3 0 =w2 w h cp;
466 fn pipe(w : world) : (world, handle, handle)
468 var rh : handle, wh : handle;
470 pcode IO IO_Pipe 3 1 0 =w2 =rh =wh w;
474 fn bopen(w : world, d : dhandle, f : bytes, flags : int, mode : int) : (world, handle)
478 pcode IO IO_Block_Open 2 5 0 =w2 =h w d f flags mode;
482 fn bread(w : world, h : handle, position : int64, size : int) : (world, bytes)
486 pcode IO IO_Block_Read 2 4 0 =w2 =s w h size position;
490 fn bwrite(w : world, h : handle, position : int64, s : bytes) : world
492 while len_greater_than(byte, s, 0) do [
495 pcode IO IO_Block_Write 2 4 0 =w2 =sz w h s position;
503 fn bsize(w : world, h : handle) : (world, int64)
507 var off : int64 := 0;
508 pcode IO IO_LSeek 2 3 1 =w2 =sz w h off 2;
512 fn bdata(w : world, h : handle, off : int64) : (world, int64)
516 pcode IO IO_LSeek 2 3 1 =w2 =sz w h off 3;
520 fn bhole(w : world, h : handle, off : int64) : (world, int64)
524 pcode IO IO_LSeek 2 3 1 =w2 =sz w h off 4;
528 fn bsetsize(w : world, h : handle, size : int64) : world
531 pcode IO IO_FTruncate 1 3 0 =w2 w h size;
535 fn bcontiguous(w : world, h : handle, pos : int64, size : int64) : world
538 pcode IO IO_FAllocate 1 4 0 =w2 w h pos size;
542 fn bclone(w : world, src_h : handle, src_pos : int64, dst_h : handle, dst_pos : int64, size : int64) : world
545 pcode IO IO_CloneRange 1 6 0 =w2 w src_h src_pos dst_h dst_pos size;
549 fn bopen_lazy(d : dhandle, f : bytes, flags : int) : handle
552 if flags <> IO_Open_Flag_Read then [
553 h := exception_make(handle, ec_sync, error_invalid_operation, 0, true);
556 var w := unsafe_get_world;
557 w, h := bopen(w, d, f, flags, 0);
561 fn bread_lazy~lazy(h : handle, position : int64) : bytes
564 var w := unsafe_get_world;
565 w, b := bread(w, h, position, 16384);
566 if len(b) < 16384 then
568 return b + bread_lazy(h, position + 16384);
571 fn bsize_lazy(h : handle) : int64
574 var w := unsafe_get_world;
575 w, sz := bsize(w, h);
579 fn bdata_lazy(h : handle, off : int64) : int64
582 var w := unsafe_get_world;
583 w, sz := bdata(w, h, off);
587 fn bhole_lazy(h : handle, off : int64) : int64
590 var w := unsafe_get_world;
591 w, sz := bhole(w, h, off);
595 fn fdatasync(w : world, h : handle) : world
598 pcode IO IO_FSync 1 2 1 =w2 w h 0;
602 fn fsync(w : world, h : handle) : world
605 pcode IO IO_FSync 1 2 1 =w2 w h 1;
609 fn ffssync(w : world, h : handle) : world
612 pcode IO IO_FSync 1 2 1 =w2 w h 2;
616 fn sync(w : world) : world
619 pcode IO IO_Sync 1 1 0 =w2 w;
623 fn droot(w : world) : dhandle
626 pcode IO IO_Root_Dir 1 1 1 =dh w 1;
630 fn dcwd(w : world) : dhandle
633 pcode IO IO_Root_Dir 1 1 1 =dh w 2;
637 fn dlib(w : world) : dhandle
640 pcode IO IO_Root_Dir 1 1 1 =dh w 3;
644 fn dexe(w : world) : dhandle
647 pcode IO IO_Root_Dir 1 1 1 =dh w 4;
651 fn dnone(w : world) : dhandle
654 pcode IO IO_Root_Dir 1 1 1 =dh w 5;
658 private fn libpath : bytes
661 pcode IO IO_Lib_Path 1 0 0 =lp;
665 fn dopen(w : world, d : dhandle, f : bytes, flags : int) : (world, dhandle)
669 pcode IO IO_Open_Dir 2 4 0 =w2 =dh w d f flags;
673 fn dread(w : world, d : dhandle) : (world, list(bytes))
675 var res : list(bytes);
677 pcode IO IO_Read_Dir 2 2 0 =w2 =res w d;
681 fn dpath(w : world, d : dhandle) : (world, bytes)
685 pcode IO IO_Dir_Path 2 2 0 =w2 =res w d;
689 fn dopen_lazy(d : dhandle, f : bytes, flags : int) : dhandle
692 var w := unsafe_get_world;
693 w, res := dopen(w, d, f, flags);
697 fn dread_lazy(d : dhandle) : list(bytes)
699 var res : list(bytes);
700 var w := unsafe_get_world;
701 w, res := dread(w, d);
705 fn dpath_lazy(d : dhandle) : bytes
708 var w := unsafe_get_world;
709 w, res := dpath(w, d);
713 type mhandle := internal_type;
715 fn dmonitor_wait(w2 : world, h : mhandle) : world
718 pcode IO IO_DMonitor_Wait 1 2 0 =w3 w2 h;
722 fn dmonitor(w : world, d : dhandle) : (world, world)
726 pcode IO IO_DMonitor_Prepare 2 2 0 =w2 =h w d;
727 w3 := dmonitor_wait~spark(w2, h);
731 const stat_flag_devmajor : int := IO_Stat_Flag_DevMajor;
732 const stat_flag_devminor : int := IO_Stat_Flag_DevMinor;
733 const stat_flag_inode : int := IO_Stat_Flag_Inode;
734 const stat_flag_type : int := IO_Stat_Flag_Type;
735 const stat_flag_mode : int := IO_Stat_Flag_Mode;
736 const stat_flag_nlink : int := IO_Stat_Flag_NLink;
737 const stat_flag_uid : int := IO_Stat_Flag_UID;
738 const stat_flag_gid : int := IO_Stat_Flag_GID;
739 const stat_flag_rdevmajor : int := IO_Stat_Flag_RDevMajor;
740 const stat_flag_rdevminor : int := IO_Stat_Flag_RDevMinor;
741 const stat_flag_size : int := IO_Stat_Flag_Size;
742 const stat_flag_optimaliosize : int := IO_Stat_Flag_OptimalIOSize;
743 const stat_flag_allocated : int := IO_Stat_Flag_Allocated;
744 const stat_flag_atime : int := IO_Stat_Flag_ATime;
745 const stat_flag_mtime : int := IO_Stat_Flag_MTime;
746 const stat_flag_ctime : int := IO_Stat_Flag_CTime;
748 const stat_type_file : int := IO_Stat_Type_File;
749 const stat_type_directory : int := IO_Stat_Type_Directory;
750 const stat_type_link : int := IO_Stat_Type_Link;
751 const stat_type_fifo : int := IO_Stat_Type_Pipe;
752 const stat_type_chardev : int := IO_Stat_Type_CharDev;
753 const stat_type_blockdev : int := IO_Stat_Type_BlockDev;
754 const stat_type_socket : int := IO_Stat_Type_Socket;
756 fn stat(w : world, d : dhandle, f : bytes, flags : int) : (world, list(int64))
758 var res : list(int64);
760 pcode IO IO_Stat 2 4 1 =w2 =res w d f flags 1;
764 fn lstat(w : world, d : dhandle, f : bytes, flags : int) : (world, list(int64))
766 var res : list(int64);
768 pcode IO IO_Stat 2 4 1 =w2 =res w d f flags 2;
772 fn fstat(w : world, h : handle, flags : int) : (world, list(int64))
774 var res : list(int64);
776 pcode IO IO_FStat 2 3 0 =w2 =res w h flags;
780 fn stat_lazy(d : dhandle, f : bytes, flags : int) : list(int64)
782 var res : list(int64);
783 var w := unsafe_get_world;
784 w, res := stat(w, d, f, flags);
788 fn lstat_lazy(d : dhandle, f : bytes, flags : int) : list(int64)
790 var res : list(int64);
791 var w := unsafe_get_world;
792 w, res := lstat(w, d, f, flags);
796 fn fstat_lazy(h : handle, flags : int) : list(int64)
798 var res : list(int64);
799 var w := unsafe_get_world;
800 w, res := fstat(w, h, flags);
804 const statfs_flag_bsize : int := IO_StatFS_Flag_BSize;
805 const statfs_flag_frsize : int := IO_StatFS_Flag_FrSize;
806 const statfs_flag_frtotal : int := IO_StatFS_Flag_FrTotal;
807 const statfs_flag_frfree : int := IO_StatFS_Flag_FrFree;
808 const statfs_flag_fravail : int := IO_StatFS_Flag_FrAvail;
809 const statfs_flag_intotal : int := IO_StatFS_Flag_InTotal;
810 const statfs_flag_infree : int := IO_StatFS_Flag_InFree;
811 const statfs_flag_inavail : int := IO_StatFS_Flag_InAvail;
812 const statfs_flag_fsid : int := IO_StatFS_Flag_FSId;
813 const statfs_flag_flags : int := IO_StatFS_Flag_Flags;
814 const statfs_flag_namelen : int := IO_StatFS_Flag_NameLen;
816 const statfs_st_readonly : int := IO_StatFS_ST_ReadOnly;
817 const statfs_st_nosuid : int := IO_StatFS_ST_NoSuid;
818 const statfs_st_nodev : int := IO_StatFS_ST_NoDev;
819 const statfs_st_noexec : int := IO_StatFS_ST_NoExec;
820 const statfs_st_synchronous : int := IO_StatFS_ST_Synchronous;
821 const statfs_st_mandlock : int := IO_StatFS_ST_MandLock;
822 const statfs_st_noatime : int := IO_StatFS_ST_NoAtime;
823 const statfs_st_nodiratime : int := IO_StatFS_ST_NoDirAtime;
824 const statfs_st_relatime : int := IO_StatFS_ST_RelAtime;
826 fn fstatfs(w : world, h : handle, flags : int) : (world, list(int64))
828 var res : list(int64);
830 pcode IO IO_FStatFS 2 3 0 =w2 =res w h flags;
834 fn dstatfs(w : world, d : dhandle, flags : int) : (world, list(int64))
836 var res : list(int64);
838 pcode IO IO_DStatFS 2 3 0 =w2 =res w d flags;
842 fn readlink(w : world, d : dhandle, f : bytes) : (world, bytes)
846 pcode IO IO_ReadLink 2 3 0 =w2 =res w d f;
850 fn readlink_lazy(d : dhandle, f : bytes) : bytes
853 var w := unsafe_get_world;
854 w, res := readlink(w, d, f);
858 fn unlink(w : world, d : dhandle, f : bytes) : world
861 pcode IO IO_Dir_Action 1 3 1 =w2 w d f IO_Action_Rm;
865 fn rmdir(w : world, d : dhandle, f : bytes) : world
868 pcode IO IO_Dir_Action 1 3 1 =w2 w d f IO_Action_Rm_Dir;
872 fn mkdir(w : world, d : dhandle, f : bytes, mode : int) : world
875 pcode IO IO_Dir_Action 1 4 1 =w2 w d f mode IO_Action_Mk_Dir;
879 fn mkpipe(w : world, d : dhandle, f : bytes, mode : int) : world
882 pcode IO IO_Dir_Action 1 4 1 =w2 w d f mode IO_Action_Mk_Pipe;
886 fn mksocket(w : world, d : dhandle, f : bytes, mode : int) : world
889 pcode IO IO_Dir_Action 1 4 1 =w2 w d f mode IO_Action_Mk_Socket;
893 fn mkchardev(w : world, d : dhandle, f : bytes, mode major minor : int) : world
896 pcode IO IO_Dir_Action 1 6 1 =w2 w d f mode major minor IO_Action_Mk_CharDev;
900 fn mkblockdev(w : world, d : dhandle, f : bytes, mode major minor : int) : world
903 pcode IO IO_Dir_Action 1 6 1 =w2 w d f mode major minor IO_Action_Mk_BlockDev;
907 fn mksymlink(w : world, d : dhandle, f t : bytes) : world
910 pcode IO IO_Dir_Action 1 4 1 =w2 w d f t IO_Action_Mk_SymLink;
914 fn mklink(w : world, d : dhandle, f : bytes, e : dhandle, t : bytes) : world
917 pcode IO IO_Dir2_Action 1 5 1 =w2 w d f e t IO_Action_Mk_Link;
921 fn rename(w : world, d : dhandle, f : bytes, e : dhandle, t : bytes) : world
924 pcode IO IO_Dir2_Action 1 5 1 =w2 w d f e t IO_Action_Rename;
928 fn chmod(w : world, d : dhandle, f : bytes, m : int) : world
931 pcode IO IO_Dir_Action 1 4 1 =w2 w d f m IO_Action_ChMod;
935 fn chown(w : world, d : dhandle, f : bytes, uid gid : int) : world
938 pcode IO IO_Dir_Action 1 5 1 =w2 w d f uid gid IO_Action_ChOwn;
942 fn lchown(w : world, d : dhandle, f : bytes, uid gid : int) : world
945 pcode IO IO_Dir_Action 1 5 1 =w2 w d f uid gid IO_Action_LChOwn;
949 fn utime(w : world, d : dhandle, f : bytes, atime mtime : int64) : world
952 pcode IO IO_Dir_Action 1 5 1 =w2 w d f mtime atime IO_Action_UTime;
956 fn lutime(w : world, d : dhandle, f : bytes, atime mtime : int64) : world
959 pcode IO IO_Dir_Action 1 5 1 =w2 w d f mtime atime IO_Action_LUTime;
964 const stty_flag_raw : int := IO_Stty_Flag_Raw;
965 const stty_flag_noecho : int := IO_Stty_Flag_Noecho;
966 const stty_flag_nosignal : int := IO_Stty_Flag_Nosignal;
967 const stty_flag_nocrlf : int := IO_Stty_Flag_NoCRLF;
969 fn stty(w : world, h : handle, flags : int) : world
972 pcode IO IO_Stty 1 3 0 =w2 w h flags;
976 fn tty_size(w : world, h : handle, x y : int) : (world, int, int)
980 pcode IO IO_Tty_Size 3 4 0 =w2 =nx =ny w h x y;
984 const uname_flag_ajla_version : int := IO_UName_Flag_Ajla_Version;
985 const uname_flag_flavor : int := IO_UName_Flag_Flavor;
986 const uname_flag_system : int := IO_UName_Flag_System;
987 const uname_flag_release : int := IO_UName_Flag_Release;
988 const uname_flag_version : int := IO_UName_Flag_Version;
989 const uname_flag_machine : int := IO_UName_Flag_Machine;
991 fn uname(flags : int) : list(bytes)
993 var res : list(bytes);
994 pcode IO IO_UName 1 1 0 =res flags;
998 fn get_host_name(w : world) : (world, bytes)
1002 pcode IO IO_GetHostName 2 1 0 =w2 =res w;
1007 fn get_real_time(w : world) : (world, int64)
1011 pcode IO IO_GetTime 2 1 1 =w2 =ret w 1;
1015 fn get_monotonic_time(w : world) : (world, int64)
1019 pcode IO IO_GetTime 2 1 1 =w2 =ret w 2;
1023 fn sleep(t : type, w : t, tm : int64) : t
1029 w3, u := get_monotonic_time(unsafe_get_world);
1031 pcode IO IO_Sleep 1 2 0 =w2 w u;
1039 const path_separator : byte
1041 var os := sysprop(SystemProperty_OS);
1042 if os = SystemProperty_OS_DOS or
1043 os = SystemProperty_OS_OS2 or
1044 os = SystemProperty_OS_Windows then
1049 fn path_is_separator(b : byte) : bool
1051 if b = '\' or b = ':' then [
1052 var os := sysprop(SystemProperty_OS);
1053 if os = SystemProperty_OS_DOS or
1054 os = SystemProperty_OS_OS2 or
1055 os = SystemProperty_OS_Cygwin or
1056 os = SystemProperty_OS_Windows then
1062 fn path_is_dir_separator(b : byte) : bool
1065 var os := sysprop(SystemProperty_OS);
1066 if os = SystemProperty_OS_DOS or
1067 os = SystemProperty_OS_OS2 or
1068 os = SystemProperty_OS_Cygwin or
1069 os = SystemProperty_OS_Windows then
1075 fn path_compare(a b : bytes) : bool
1077 var os := sysprop(SystemProperty_OS);
1078 if os = SystemProperty_OS_DOS or
1079 os = SystemProperty_OS_OS2 or
1080 os = SystemProperty_OS_Windows then [
1081 if len(a) <> len(b) then
1083 for i := 0 to len(a) do [
1086 if a1 >= 'a', a1 <= 'z' then
1088 if b1 >= 'a', b1 <= 'z' then
1098 fn dos_path_is_absolute(p : bytes) : bool
1100 if len_at_least(p, 3), (p[0] and #DF) >= 'A', (p[0] and #DF) <= 'Z', p[1] = ':', path_is_dir_separator(p[2]) then
1102 if len_at_least(p, 2), path_is_dir_separator(p[0]), path_is_dir_separator(p[1]) then
1107 fn path_is_absolute(p : bytes) : bool
1109 var os := sysprop(SystemProperty_OS);
1110 if os = SystemProperty_OS_DOS or
1111 os = SystemProperty_OS_OS2 or
1112 os = SystemProperty_OS_Windows then [
1113 return dos_path_is_absolute(p);
1115 if len_at_least(p, 1), path_is_dir_separator(p[0]) then
1117 if os = SystemProperty_OS_Cygwin then
1118 return dos_path_is_absolute(p);
1122 fn path_is_root(p : bytes) : bool
1124 p := path_contract(p);
1125 if len(p) = 1, path_is_dir_separator(p[0]) then
1127 var os := sysprop(SystemProperty_OS);
1128 if os = SystemProperty_OS_DOS or
1129 os = SystemProperty_OS_OS2 or
1130 os = SystemProperty_OS_Cygwin or
1131 os = SystemProperty_OS_Windows then [
1132 if len(p) = 3, (p[0] and #DF) >= 'A', (p[0] and #DF) <= 'Z', p[1] = ':', path_is_dir_separator(p[2]) then
1138 fn path_to_dir_file(p : bytes) : (bytes, bytes)
1140 var idx := list_search_backwards_fn(p, path_is_separator);
1141 var dir := p[ .. idx + 1];
1142 var file := p[idx + 1 .. ];
1143 if file = "." or file = ".." then [
1144 dir := p +< path_separator;
1148 dir := "." + bytes.[ path_separator ];
1149 if len(dir) > 1 then
1150 dir := dir[ .. len(dir) - 1];
1154 fn path_append(pd pf : bytes) : bytes
1156 if len(pd) > 0, not path_is_separator(pd[len(pd) - 1]) then
1157 pd += bytes.[ path_separator ];
1161 fn path_contract_unix(p : bytes, trim_dot : bool) : bytes
1163 for i := 0 to len(p) do [
1164 if path_is_dir_separator(p[i]) then
1167 var leading_slash := false;
1168 if len_at_least(p, 1), p[0] = '/' then [
1170 leading_slash := true;
1172 var components := list_break(p, '/');
1173 var result := empty(bytes);
1174 for i := 0 to len(components) do [
1175 if components[i] = "" then
1177 if components[i] = ".", trim_dot then
1179 if components[i] = ".." then [
1180 if len(result) >= 1 then [
1181 if result[len(result) - 1] = ".." then
1183 result := result[ .. len(result) - 1];
1186 if leading_slash then
1191 result +<= components[i];
1194 if leading_slash then
1195 r +<= path_separator;
1196 for i := 0 to len(result) do [
1198 r +<= path_separator;
1206 fn path_contract(p : bytes) : bytes
1208 if path_is_separator(':') then [
1209 if len_at_least(p, 2), (p[0] and #DF) >= 'A', (p[0] and #DF) <= 'Z', p[1] = ':' then
1210 return p[ .. 2] + path_contract_unix(p[2 .. ], true);
1211 if len_at_least(p, 2), path_is_dir_separator(p[0]), path_is_dir_separator(p[1]) then
1212 return [ path_separator ] + path_contract_unix(p[1 .. ], false);
1214 return path_contract_unix(p, true);
1217 fn path_join(pd pf : bytes) : bytes
1219 if path_is_absolute(pf) then
1220 return path_contract(pf);
1221 if path_is_separator(':') then [
1222 if len_at_least(pf, 1), path_is_separator(pf[0]) then [
1223 if len_at_least(pd, 2), (pd[0] and #DF) >= 'A', (pd[0] and #DF) <= 'Z', pd[1] = ':' then [
1224 return path_contract(pd[ .. 2] + pf);
1226 if len_at_least(pd, 2), path_is_dir_separator(pd[0]), path_is_dir_separator(pd[1]) then [
1227 return path_contract(pd[ .. 1] + pf);
1229 return path_contract(pf);
1231 if len_at_least(pf, 2), (pf[0] and #DF) >= 'A', (pf[0] and #DF) <= 'Z', pf[1] = ':' then [
1232 if len_at_least(pd, 3), (pd[0] and #DF) = (pf[0] and #DF), pd[1] = ':', path_is_dir_separator(pd[2]) then [
1235 return path_contract(pf[ .. 2] + [ path_separator ] + pf[2 .. ]);
1239 return path_contract(path_append(pd, pf));
1242 fn path_canonical(implicit w : world, d : dhandle, p : bytes) : (world, bytes)
1244 var dir, file := path_to_dir_file(p);
1245 var pd := dopen(d, dir, 0);
1246 var pdp := dpath(pd);
1247 var pj := path_append(pdp, file);
1251 fn path_get_cwd(implicit w : world, d : dhandle, env : treemap(bytes, bytes)) : (world, bytes)
1254 var t := treemap_search(env, "PWD");
1255 if t is j, path_is_absolute(t.j) then [
1256 var ctr := path_contract(t.j);
1258 var pd2 := dopen(dnone(), ctr, 0);
1259 if is_exception pd2 then [
1260 recover_world(old_w);
1264 var p2 := dpath(pd2);
1265 if is_exception p2 then [
1266 recover_world(old_w);
1275 fn path_shortcut_home(home : maybe(bytes), p : bytes) : bytes
1279 if not path_is_absolute(home.j) then
1281 var h := path_contract(home.j);
1284 if len(h) < len(p), path_compare(h, p[ .. len(h)]), path_is_dir_separator(p[len(h)]) then
1285 return "~" + p[len(h) .. ];
1289 fn path_expand_home(home : maybe(bytes), p : bytes) : bytes
1294 if not path_is_absolute(h) then
1296 h := path_contract(h);
1299 if len(p) >= 2, p[0] = '~', path_is_dir_separator(p[1]) then [
1301 while len(p) > i, path_is_dir_separator(p[i]) do
1303 return path_append(h, p[i .. ]);
1308 fn path_mkdir_step(implicit w : world, d : dhandle, f : bytes, mode : int) : world
1312 if is_exception w then [
1313 if exception_type w = error_system, exception_aux w = system_error_eexist then [
1319 fn path_mkdir(implicit w : world, d : dhandle, f : bytes, mode : int) : world
1322 path_mkdir_step(d, f, mode);
1323 if not is_exception w then
1328 while i < len(f), path_is_separator(f[i]) do
1330 if i = 0, path_is_absolute(f) then [
1331 while i < len(f), not path_is_separator(f[i]) do
1333 while i < len(f), path_is_separator(f[i]) do
1337 while i < len(f) do [
1338 while i < len(f), not path_is_separator(f[i]) do
1340 while i < len(f), path_is_separator(f[i]) do
1342 path_mkdir_step(d, f[ .. i], mode);
1347 fn path_xdg(implicit w : world, env : treemap(bytes, bytes), xdg_env : bytes, deflt : bytes, appname : bytes) : (world, dhandle)
1352 var x := treemap_search(env, xdg_env);
1354 if path_is_absolute(x.j) then [
1359 if sysprop(SystemProperty_OS) = SystemProperty_OS_Windows then [
1360 x := treemap_search(env, "APPDATA");
1364 x := treemap_search(env, "HOME");
1367 var a := path_append(x.j, deflt);
1368 if path_is_absolute(a) then [
1375 d := path_append(d, appname);
1376 path_mkdir(dnone(), d, #1c0);
1377 if is_exception w then [
1378 if len(deflt) > 0, deflt[0] = '.' then [
1380 deflt := deflt[1 .. ];
1384 return dopen(dnone(), d, 0);
1387 fn path_config(implicit w : world, env : treemap(bytes, bytes), appname : bytes) : (world, dhandle)
1389 return path_xdg(env, "XDG_CONFIG_HOME", ".config", appname);
1392 fn path_write_atomic(implicit w : world, d : dhandle, f : bytes, content : bytes) : world
1396 var i := len(tmp_file) - 1;
1398 if path_is_separator(tmp_file[i]) then
1400 if tmp_file[i] = '.' then [
1401 tmp_file := tmp_file[ .. i];
1410 var tmp_file_x := tmp_file + ntos(num);
1411 var wf := wopen(d, tmp_file_x, open_flag_create or open_flag_must_create, #180);
1412 if is_exception w, exception_aux w = system_error_eexist, not is_exception w1 then [
1418 rename(d, f, d, tmp_file_x);
1419 if is_exception w then [
1422 unlink(d, tmp_file);
1434 fn register_dependence(implicit w : world, d : dhandle, p : bytes) : world
1436 var cp := path_canonical(d, p);
1438 pcode IO IO_Register_Dependence 1 2 0 =w2 w cp;