moros/usr/
install.rs

1use crate::api::console::Style;
2use crate::api::fs;
3use crate::api::io;
4use crate::api::process::ExitCode;
5use crate::api::syscall;
6use crate::{api, sys, usr};
7
8use alloc::format;
9use alloc::string::String;
10
11macro_rules! copy_file {
12    ($path:expr, $verbose:expr) => ({
13        copy_file($path, include_bytes!(concat!("../../dsk", $path)), $verbose);
14    });
15}
16
17pub fn copy_files(verbose: bool) {
18    create_dir("/bin", verbose); // Binaries
19    create_dir("/dev", verbose); // Devices
20    create_dir("/ini", verbose); // Initializers
21    create_dir("/lib", verbose); // Libraries
22    create_dir("/net", verbose); // Network
23    create_dir("/src", verbose); // Sources
24    create_dir("/tmp", verbose); // Temporaries
25    create_dir("/usr", verbose); // User directories
26    create_dir("/var", verbose); // Variables
27
28    // NOTE: Here are the binaries to be included in the build image, but they
29    // can also be installed later with the `pkg install` command.
30
31    //copy_file!("/bin/blank", verbose);
32    //copy_file!("/bin/browse", verbose);
33    copy_file!("/bin/clear", verbose);
34    //copy_file!("/bin/exec", verbose);
35    //copy_file!("/bin/fetch", verbose);
36    //copy_file!("/bin/geocal", verbose);
37    //copy_file!("/bin/geodate", verbose);
38    copy_file!("/bin/halt", verbose);
39    //copy_file!("/bin/hello", verbose);
40    //copy_file!("/bin/mandelbrot", verbose);
41    copy_file!("/bin/ntp", verbose);
42    copy_file!("/bin/pkg", verbose);
43    copy_file!("/bin/print", verbose);
44    copy_file!("/bin/reboot", verbose);
45    copy_file!("/bin/sleep", verbose);
46
47    create_dir("/dev/ata", verbose); // Drives
48    create_dir("/dev/ata/0", verbose);
49    create_dir("/dev/ata/1", verbose);
50    create_dir("/dev/clk", verbose); // Clock
51    create_dir("/dev/net", verbose); // Network
52    create_dir("/dev/vga", verbose);
53
54    create_dev("/dev/ata/0/0", "ata-0-0", verbose);
55    create_dev("/dev/ata/0/1", "ata-0-1", verbose);
56    create_dev("/dev/ata/1/0", "ata-1-0", verbose);
57    create_dev("/dev/ata/1/1", "ata-1-1", verbose);
58    create_dev("/dev/clk/boot", "clk-boot", verbose);
59    create_dev("/dev/clk/epoch", "clk-epoch", verbose);
60    create_dev("/dev/clk/rtc", "clk-rtc", verbose);
61    create_dev("/dev/console", "console", verbose);
62    create_dev("/dev/net/tcp", "net-tcp", verbose);
63    create_dev("/dev/net/udp", "net-udp", verbose);
64    create_dev("/dev/net/gw", "net-gw", verbose);
65    create_dev("/dev/net/ip", "net-ip", verbose);
66    create_dev("/dev/net/mac", "net-mac", verbose);
67    create_dev("/dev/net/usage", "net-usage", verbose);
68    create_dev("/dev/null", "null", verbose);
69    create_dev("/dev/random", "random", verbose);
70    create_dev("/dev/speaker", "speaker", verbose);
71    create_dev("/dev/vga/buffer", "vga-buffer", verbose);
72    create_dev("/dev/vga/font", "vga-font", verbose);
73    create_dev("/dev/vga/mode", "vga-mode", verbose);
74    create_dev("/dev/vga/palette", "vga-palette", verbose);
75
76    copy_file!("/ini/banner.txt", verbose);
77    copy_file!("/ini/boot.sh", verbose);
78    copy_file!("/ini/lisp.lsp", verbose);
79    copy_file!("/ini/shell.sh", verbose);
80    copy_file!("/ini/version.txt", verbose);
81
82    create_dir("/ini/palettes", verbose);
83    copy_file!("/ini/palettes/default.sh", verbose);
84    copy_file!("/ini/palettes/gruvbox-dark.sh", verbose);
85    copy_file!("/ini/palettes/gruvbox-light.sh", verbose);
86
87    create_dir("/ini/fonts", verbose);
88    //copy_file!("/ini/fonts/lat15-terminus-8x16.psf", verbose);
89    copy_file!("/ini/fonts/zap-light-8x16.psf", verbose);
90    //copy_file!("/ini/fonts/zap-vga-8x16.psf", verbose);
91
92    create_dir("/lib/lisp", verbose);
93    copy_file!("/lib/lisp/alias.lsp", verbose);
94    copy_file!("/lib/lisp/core.lsp", verbose);
95    copy_file!("/lib/lisp/file.lsp", verbose);
96    copy_file!("/lib/lisp/ini.lsp", verbose);
97    //copy_file!("/lib/lisp/legacy.lsp", verbose);
98    copy_file!("/lib/lisp/math.lsp", verbose);
99
100    copy_file!("/tmp/alice.txt", verbose);
101    //copy_file!("/tmp/machines.txt", verbose);
102    //copy_file!("/tmp/roads.txt", verbose);
103
104    //create_dir("/tmp/chess", verbose);
105    //copy_file!("/tmp/chess/mi2.epd", verbose);
106    //copy_file!("/tmp/chess/mi3.epd", verbose);
107    //copy_file!("/tmp/chess/mi4.epd", verbose);
108    //copy_file!("/tmp/chess/puru.epd", verbose);
109
110    //create_dir("/tmp/lisp", verbose);
111    //copy_file!("/tmp/lisp/colors.lsp", verbose);
112    //copy_file!("/tmp/lisp/doc.lsp", verbose);
113    //copy_file!("/tmp/lisp/factorial.lsp", verbose);
114    //copy_file!("/tmp/lisp/fibonacci.lsp", verbose);
115    //copy_file!("/tmp/lisp/geotime.lsp", verbose);
116    //copy_file!("/tmp/lisp/pi.lsp", verbose);
117    //copy_file!("/tmp/lisp/sum.lsp", verbose);
118    //copy_file!("/tmp/lisp/tak.lsp", verbose);
119
120    //create_dir("/tmp/life", verbose);
121    //copy_file!("/tmp/life/centinal.cells", verbose);
122    //copy_file!("/tmp/life/flower-of-eden.cells", verbose);
123    //copy_file!("/tmp/life/garden-of-eden.cells", verbose);
124    //copy_file!("/tmp/life/glider-gun.cells", verbose);
125    //copy_file!("/tmp/life/pentadecathlon.cells", verbose);
126    //copy_file!("/tmp/life/queen-bee-shuttle.cells", verbose);
127    //copy_file!("/tmp/life/ship-in-a-bottle.cells", verbose);
128    //copy_file!("/tmp/life/thunderbird.cells", verbose);
129    //copy_file!("/tmp/life/wing.cells", verbose);
130
131    //create_dir("/tmp/beep", verbose);
132    //copy_file!("/tmp/beep/tetris.sh", verbose);
133    //copy_file!("/tmp/beep/starwars.sh", verbose);
134    //copy_file!("/tmp/beep/mario.sh", verbose);
135
136    create_dir("/var/log", verbose);
137
138    create_dir("/var/www", verbose);
139    copy_file!("/var/www/index.html", verbose);
140    copy_file!("/var/www/moros.css", verbose);
141    copy_file!("/var/www/moros.png", verbose);
142
143    create_dir("/var/pkg", verbose);
144}
145
146pub fn main(args: &[&str]) -> Result<(), ExitCode> {
147    let csi_color = Style::color("yellow");
148    let csi_reset = Style::reset();
149    println!(
150        "{}Welcome to MOROS v{} installation program!{}",
151        csi_color,
152        env!("CARGO_PKG_VERSION"),
153        csi_reset
154    );
155    println!();
156
157    let mut has_confirmed = false;
158    for &arg in args {
159        match arg {
160            "-y" | "--yes" => has_confirmed = true,
161            _ => continue,
162        }
163    }
164    if !has_confirmed {
165        print!("Proceed? [y/N] ");
166        has_confirmed = io::stdin().read_line().trim() == "y";
167        println!();
168    }
169
170    if has_confirmed {
171        if !sys::fs::is_mounted() {
172            println!("{}Listing disks ...{}", csi_color, csi_reset);
173            usr::shell::exec("disk list").ok();
174            println!("/dev/mem        RAM DISK");
175            println!();
176
177            println!("{}Formatting disk ...{}", csi_color, csi_reset);
178            print!("Enter path of disk to format: ");
179            let path = io::stdin().read_line();
180            if path.trim_end() == "/dev/mem" {
181                usr::shell::exec(&format!("memory format"))?;
182            } else {
183                usr::shell::exec(&format!("disk format {}", path.trim_end()))?;
184            }
185            println!();
186        }
187
188        println!("{}Populating filesystem...{}", csi_color, csi_reset);
189        let verbose = true;
190        copy_files(verbose);
191
192        if sys::process::user().is_none() {
193            println!();
194            println!("{}Creating user...{}", csi_color, csi_reset);
195            let res = usr::user::main(&["user", "create"]);
196            if res == Err(ExitCode::Failure) {
197                return res;
198            }
199        }
200
201        println!();
202        println!("{}Installation successful!{}", csi_color, csi_reset);
203        println!();
204        println!("Quit the console or reboot to apply changes");
205    }
206
207    Ok(())
208}
209
210fn create_dir(path: &str, verbose: bool) {
211    if fs::exists(path) {
212        return;
213    }
214    if verbose {
215        println!("Creating '{}'", path);
216    }
217    if let Some(handle) = api::fs::create_dir(path) {
218        syscall::close(handle);
219    }
220}
221
222fn create_dev(path: &str, name: &str, verbose: bool) {
223    if fs::exists(path) {
224        return;
225    }
226    if verbose {
227        println!("Creating '{}'", path);
228    }
229    if let Some(handle) = fs::create_device(path, name) {
230        syscall::close(handle);
231    }
232}
233
234fn copy_file(path: &str, buf: &[u8], verbose: bool) {
235    if fs::exists(path) {
236        return;
237    }
238    if verbose {
239        println!("Fetching '{}'", path);
240    }
241    if path.ends_with(".txt") {
242        if let Ok(text) = String::from_utf8(buf.to_vec()) {
243            let text = text.replace("{x.x.x}", env!("CARGO_PKG_VERSION"));
244            fs::write(path, text.as_bytes()).ok();
245        } else {
246            fs::write(path, buf).ok();
247        }
248    } else {
249        fs::write(path, buf).ok();
250    }
251}