Phasor 2.2.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
touch.phs
Go to the documentation of this file.
1// Port of touch -- change modification and access times of files for GNU.
2// 'touch' file modification program for Phasor.
3// Copyright (C) 2026 Daniel McGuire.
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18include_stdfile();
19include_stdsys();
20include_stdstr();
21include_stdtype();
22include_stdio();
23
24// Global variables for options
25var g_no_create = false;
26var g_no_dereference = false;
27var g_update_atime = true;
28var g_update_mtime = true;
29var g_reference = null;
30var g_date = null;
31var g_timestamp = null;
32var g_error_occurred = false;
33
34fn startsWith(input: string, prefix: string) {
35 if (len(input) < len(prefix)) return false;
36 return substr(input, 0, len(prefix)) == prefix;
37}
38
39// Function to display help message
40fn show_help() -> void {
41 puts("Usage: touch [OPTION]... FILE");
42 puts("Update the access and modification times of FILE to the current time.");
43 puts("If FILE does not exist, it is created empty, unless -c is supplied.");
44 puts("");
45 puts("Options:");
46 puts(" -a change only the access time");
47 puts(" -c, --no-create do not create any files");
48 puts(" -d, --date=STRING parse STRING and use as time");
49 puts(" -h, --no-dereference affect symbolic links directly");
50 puts(" -m change only the modification time");
51 puts(" -r, --reference=FILE use this file's times");
52 puts(" --help display this help and exit");
53 puts(" --version output version information and exit");
54}
55
56// Function to display version information
57fn show_version() -> void {
58 puts("touch (Phasor coreutils) 0.1");
59 puts("License GPLv3+: GNU GPL version 3 or later");
60 puts("This is free software: you are free to change and redistribute it.");
61 puts("There is NO WARRANTY, to the extent permitted by law.");
62}
63
64// Function to parse date string
65fn parse_date(date_str: string) -> int {
66 return time() / 1000;
67}
68
69// Function to get time from reference file
70fn get_reference_time(ref_file: string) -> int {
71 if (!fexists(ref_file)) {
72 puts("touch: cannot stat reference file");
73 g_error_occurred = true;
74 return 0;
75 }
76 return fpropget(ref_file, "m", 0);
77}
78
79// Main touch function
80fn touch_file(filename: string) -> void {
81 var current_time = time() / 1000;
82 var target_time = current_time;
83
84 if (g_reference) {
85 target_time = get_reference_time(g_reference);
86 if (g_error_occurred) return;
87 } else if (g_date) {
88 target_time = parse_date(g_date);
89 } else if (g_timestamp) {
90 target_time = to_int(g_timestamp);
91 }
92
93 var exists = fexists(filename);
94
95 if (!exists) {
96 if (g_no_create) return;
97 if (!fmk(filename)) {
98 puts("touch: cannot create file");
99 g_error_occurred = true;
100 return;
101 }
102 }
103
104 if (g_update_atime && !fpropset(filename, "a", target_time)) {
105 puts("touch: cannot update access time");
106 g_error_occurred = true;
107 }
108
109 if (g_update_mtime && !fpropset(filename, "m", target_time)) {
110 puts("touch: cannot update modification time");
111 g_error_occurred = true;
112 }
113}
114
115fn main() -> int {
116 var arg_count = sys_argc();
117 var filename = null;
118
119 for (var i = 1; i < arg_count; i = i + 1) {
120 var arg = sys_argv(i);
121
122 if (arg == "--help") {
123 show_help();
124 return 0;
125 } else if (arg == "--version") {
126 show_version();
127 return 0;
128 } else if (arg == "--") {
129 i = i + 1;
130 break;
131 } else if (arg == "--no-create" || arg == "-c") {
132 g_no_create = true;
133 } else if (arg == "--no-dereference" || arg == "-h") {
134 g_no_dereference = true;
135 } else if (arg == "-a") {
136 g_update_atime = true;
137 g_update_mtime = false;
138 } else if (arg == "-m") {
139 g_update_atime = false;
140 g_update_mtime = true;
141 } else if (startsWith(arg, "-") && len(arg) > 1) {
142 for (var j = 1; j < len(arg); j = j + 1) {
143 var opt = substr(arg, j, 1);
144 if (opt == "a") {
145 g_update_atime = true;
146 g_update_mtime = false;
147 } else if (opt == "c") {
148 g_no_create = true;
149 } else if (opt == "h") {
150 g_no_dereference = true;
151 } else if (opt == "m") {
152 g_update_atime = false;
153 g_update_mtime = true;
154 } else {
155 puts("touch: invalid option");
156 puts("Try 'touch --help' for more information.");
157 return 1;
158 }
159 }
160 } else {
161 filename = arg;
162 }
163 }
164
165 if (filename == null) {
166 puts("touch: missing file operand");
167 puts("Try 'touch --help' for more information.");
168 return 1;
169 }
170
171 touch_file(filename);
172
173 if (g_error_occurred) {
174 return 1;
175 }
176 return 0;
177}
178
179shutdown(main());