Merge branch libfileis
This commit is contained in:
		
						commit
						941f931f8b
					
				
							
								
								
									
										14
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Makefile
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | ||||
| # Copyright (c) 2023–2024 Emma Tebibyte <emma@tebibyte.media>
 | ||||
| # Copyright (c) 2023–2025 Emma Tebibyte <emma@tebibyte.media>
 | ||||
| # Copyright (c) 2023–2024 DTB <trinity@trinity.moe>
 | ||||
| # Copyright (c) 2023 Sasha Koshka <sashakoshka@tebibyte.media>
 | ||||
| # Copyright (c) 2024 Aaditya Aryal <aryalaadi123@gmail.com>
 | ||||
| @ -42,7 +42,7 @@ BIN = build/bin | ||||
| default: all test | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: dj false fop hru intcmp mm npc peek rpn scrut str strcmp swab true | ||||
| all: dj false fileis fop hru intcmp mm npc peek rpn str strcmp swab true | ||||
| 
 | ||||
| # keep build/include until bindgen(1) has stdin support
 | ||||
| # https://github.com/rust-lang/rust-bindgen/issues/2703
 | ||||
| @ -112,6 +112,11 @@ false: build/bin/false | ||||
| build/bin/false: src/false.c build | ||||
| 	$(CC) $(CFLAGS) -o $@ src/false.c | ||||
| 
 | ||||
| .PHONY: fileis | ||||
| fileis: build/bin/fileis | ||||
| build/bin/fileis: src/fileis.rs build | ||||
| 	$(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/fileis.rs | ||||
| 
 | ||||
| .PHONY: fop | ||||
| fop: build/bin/fop | ||||
| build/bin/fop: src/fop.rs build rustlibs | ||||
| @ -147,11 +152,6 @@ rpn: build/bin/rpn | ||||
| build/bin/rpn: src/rpn.rs build rustlibs | ||||
| 	$(RUSTC) $(RUSTFLAGS) -o $@ src/rpn.rs | ||||
| 
 | ||||
| .PHONY: scrut | ||||
| scrut: build/bin/scrut | ||||
| build/bin/scrut: src/scrut.c build | ||||
| 	$(CC) $(CFLAGS) -o $@ src/scrut.c | ||||
| 
 | ||||
| .PHONY: str | ||||
| str: build/bin/str | ||||
| build/bin/str: src/str.c build | ||||
|  | ||||
| @ -1,15 +1,15 @@ | ||||
| .\" Copyright (c) 2024 DTB <trinity@trinity.moe> | ||||
| .\" Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media> | ||||
| .\" Copyright (c) 2024–2025 Emma Tebibyte <emma@tebibyte.media> | ||||
| .\" | ||||
| .\" This work is licensed under CC BY-SA 4.0. To see a copy of this license, | ||||
| .\" visit <http://creativecommons.org/licenses/by-sa/4.0/>. | ||||
| .\" | ||||
| .TH SCRUT 1 2024-06-06 "Harakit X.X.X" | ||||
| .TH FILEIS 1 2025-02-24 "Harakit X.X.X" | ||||
| .SH NAME | ||||
| scrut \(en scrutinize file properties | ||||
| fileis \(en scrutinize file properties | ||||
| .SH SYNOPSIS | ||||
| 
 | ||||
| scrut | ||||
| fileis | ||||
| .RB [ -LSbcdefgkprsuwx ] | ||||
| .B file... | ||||
| .\" | ||||
| @ -82,5 +82,6 @@ Copyright \(co 2024 DTB. License AGPLv3+: GNU AGPL version 3 or later | ||||
| .\" | ||||
| .SH SEE ALSO | ||||
| .BR access (3p), | ||||
| .BR chown (1p), | ||||
| .BR lstat (3p), | ||||
| .BR test (1p) | ||||
							
								
								
									
										91
									
								
								src/fileis.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/fileis.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | ||||
| /* | ||||
|  * Copyright (c) 2024 DTB <trinity@trinity.moe> | ||||
|  * Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media> | ||||
|  * SPDX-License-Identifier: AGPL-3.0-or-later | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify it under | ||||
|  * the terms of the GNU Affero General Public License as published by the Free | ||||
|  * Software Foundation, either version 3 of the License, or (at your option) any | ||||
|  * later version. | ||||
|  * 
 | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | ||||
|  * details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program. If not, see https://www.gnu.org/licenses/.
 | ||||
|  */ | ||||
| 
 | ||||
| use std::{ | ||||
| 	env::args, | ||||
| 	fs::metadata, | ||||
| 	os::unix::fs::{ FileTypeExt, MetadataExt }, | ||||
| 	process::ExitCode, | ||||
| }; | ||||
| 
 | ||||
| extern crate getopt; | ||||
| extern crate strerror; | ||||
| extern crate sysexits; | ||||
| 
 | ||||
| use getopt::GetOpt; | ||||
| use strerror::StrError; | ||||
| use sysexits::EX_USAGE; | ||||
| 
 | ||||
| const OPTS: &str = "bcdefgkprsuwxLS"; | ||||
| 
 | ||||
| fn usage(argv0: &str) -> ExitCode { | ||||
| 	eprintln!("Usage: {} [-{}] file...", argv0, OPTS); | ||||
| 	ExitCode::from(EX_USAGE) | ||||
| } | ||||
| 
 | ||||
| fn main() -> ExitCode { | ||||
| 	let argv = args().collect::<Vec<_>>(); | ||||
| 
 | ||||
| 	let mut sel = String::with_capacity(OPTS.len()); // selected options
 | ||||
| 	let mut optind: usize = 1; // argv[0]
 | ||||
| 
 | ||||
| 	while let Some(opt) = argv.getopt(OPTS) { | ||||
| 		if let Ok(optchr) = opt.opt() { sel.push_str(optchr); } | ||||
| 		else { return usage(&argv[0]); } | ||||
| 
 | ||||
| 		optind = opt.ind(); | ||||
| 	} | ||||
| 
 | ||||
| 	if optind == argv.len() { return usage(&argv[0]); } | ||||
| 
 | ||||
| 	for arg in argv.iter().skip(optind) { | ||||
| 		let fmeta = match metadata(arg) { | ||||
| 			Ok(m) => m, | ||||
| 			Err(e) => { // no perms or nonexistent
 | ||||
| 				eprintln!("{}: {}: {}", argv[0], arg, e.strerror()); | ||||
| 				return ExitCode::FAILURE; | ||||
| 			}, | ||||
| 		}; | ||||
| 
 | ||||
| 		let fmode = fmeta.mode(); | ||||
| 		let ftype = fmeta.file_type(); | ||||
| 
 | ||||
| 		for selection in sel.chars() { // run all selected tests
 | ||||
| 			match selection { | ||||
| 				'b' if ftype.is_block_device() => (), | ||||
| 				'c' if ftype.is_char_device() => (), | ||||
| 				'e' => (), // exists or metadata would have errored
 | ||||
| 				'd' if fmeta.is_dir() => (), | ||||
| 				'f' if fmeta.is_file() => (), | ||||
| 				'g' if fmode & 0o2000 /* S_ISGID */ != 0 => (), // setgid
 | ||||
| 				'k' if fmode & 0o1000 /* S_ISVTX */ != 0 => (), // setvtx
 | ||||
| 				'p' if ftype.is_fifo() => (), | ||||
| 				'r' if fmode & 0o0400 /* S_IRUSR */ != 0 => (), // read access
 | ||||
| 				'u' if fmode & 0o4000 /* S_ISUID */ != 0 => (), // setuid
 | ||||
| 				'w' if fmode & 0o0200 /* S_IWUSR */ != 0 => (), // write access
 | ||||
| 				'x' if fmode & 0o0100 /* S_IXUSR */ != 0 => (), // exec access
 | ||||
| 				'L' if fmeta.is_symlink() => (), | ||||
| 				'S' if ftype.is_socket() => (), | ||||
| 				_ => { return ExitCode::FAILURE; } | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ExitCode::SUCCESS | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user