forked from Bananymous/banan-os
				
			Userspace: add basic ls command
This commit is contained in:
		
							parent
							
								
									83a6e6f637
								
							
						
					
					
						commit
						1cf464d5c7
					
				| 
						 | 
					@ -3,9 +3,10 @@ cmake_minimum_required(VERSION 3.26)
 | 
				
			||||||
project(userspace CXX)
 | 
					project(userspace CXX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(USERSPACE_PROJECTS
 | 
					set(USERSPACE_PROJECTS
 | 
				
			||||||
	Shell
 | 
					 | 
				
			||||||
	cat
 | 
						cat
 | 
				
			||||||
	echo
 | 
						echo
 | 
				
			||||||
 | 
						ls
 | 
				
			||||||
 | 
						Shell
 | 
				
			||||||
	test
 | 
						test
 | 
				
			||||||
	yes
 | 
						yes
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 3.26)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project(ls CXX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(SOURCES
 | 
				
			||||||
 | 
						main.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(ls ${SOURCES})
 | 
				
			||||||
 | 
					target_compile_options(ls PUBLIC -O2 -g)
 | 
				
			||||||
 | 
					target_link_libraries(ls PUBLIC libc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_custom_target(ls-install
 | 
				
			||||||
 | 
						COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/ls ${BANAN_BIN}/
 | 
				
			||||||
 | 
						DEPENDS ls
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,144 @@
 | 
				
			||||||
 | 
					#include <dirent.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool all { false };
 | 
				
			||||||
 | 
					bool list { false };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char* mode_string(mode_t mode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static char buffer[11];
 | 
				
			||||||
 | 
						buffer[0] =	(mode & 0770000) == S_IFLNK ? 'l' :
 | 
				
			||||||
 | 
									(mode & 0770000) == S_IFDIR ? 'd' :
 | 
				
			||||||
 | 
									(mode & 0770000) == S_IFBLK ? 'b' :
 | 
				
			||||||
 | 
									(mode & 0770000) == S_IFCHR ? 'c' :
 | 
				
			||||||
 | 
									'-';
 | 
				
			||||||
 | 
						buffer[1] = mode & S_IRUSR ? 'r' : '-';
 | 
				
			||||||
 | 
						buffer[2] = mode & S_IWUSR ? 'w' : '-';
 | 
				
			||||||
 | 
						buffer[3] = mode & S_IXUSR ? 'x' : '-';
 | 
				
			||||||
 | 
						buffer[4] = mode & S_IRGRP ? 'r' : '-';
 | 
				
			||||||
 | 
						buffer[5] = mode & S_IWGRP ? 'w' : '-';
 | 
				
			||||||
 | 
						buffer[6] = mode & S_IXGRP ? 'x' : '-';
 | 
				
			||||||
 | 
						buffer[7] = mode & S_IROTH ? 'r' : '-';
 | 
				
			||||||
 | 
						buffer[8] = mode & S_IWOTH ? 'w' : '-';
 | 
				
			||||||
 | 
						buffer[9] = mode & S_IXOTH ? 'x' : '-';
 | 
				
			||||||
 | 
						buffer[10] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return buffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void list_directory(const char* path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DIR* dirp = opendir(path);
 | 
				
			||||||
 | 
						if (dirp == nullptr)
 | 
				
			||||||
 | 
							return perror("opendir");
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						errno = 0;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						bool first = true;
 | 
				
			||||||
 | 
						while (auto* dirent = readdir(dirp))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (!all && dirent->d_name[0] == '.')
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (list)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (!first)
 | 
				
			||||||
 | 
									printf("\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								struct stat st;
 | 
				
			||||||
 | 
								if (fstatat(dirfd(dirp), dirent->d_name, &st, AT_SYMLINK_NOFOLLOW) == -1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									perror("stat");
 | 
				
			||||||
 | 
									printf("?????????? ???? %s", dirent->d_name);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									printf("%s %d %s", mode_string(st.st_mode), st.st_size, dirent->d_name);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (!first)
 | 
				
			||||||
 | 
									printf(" ");
 | 
				
			||||||
 | 
								printf("%s", dirent->d_name);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							first = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (errno != 0)
 | 
				
			||||||
 | 
							perror("readdir");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf("\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						closedir(dirp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void print_usage()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						printf("Usage: ls [OPTION]... [FILE]...\n");
 | 
				
			||||||
 | 
						printf("  -a, --all     show all files\n");
 | 
				
			||||||
 | 
						printf("  -l, --list    print files on separate lines\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char** argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int arg = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (arg < argc && argv[arg][0] == '-')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (strcmp(argv[arg], "--all") == 0)
 | 
				
			||||||
 | 
								all = true;
 | 
				
			||||||
 | 
							else if (strcmp(argv[arg], "--list") == 0)
 | 
				
			||||||
 | 
								list = true;
 | 
				
			||||||
 | 
							else if (strcmp(argv[arg], "--help") == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								print_usage();
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								for (int i = 1; argv[arg][i]; i++)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									char c = argv[arg][i];
 | 
				
			||||||
 | 
									if (c == 'a')
 | 
				
			||||||
 | 
										all = true;
 | 
				
			||||||
 | 
									else if (c == 'l')
 | 
				
			||||||
 | 
										list = true;
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										print_usage();
 | 
				
			||||||
 | 
										return 1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							arg++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (arg == argc)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							list_directory(".");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (arg + 1 == argc)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							list_directory(argv[arg]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							for (int i = arg; i < argc; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (i > arg)
 | 
				
			||||||
 | 
									printf("\n");
 | 
				
			||||||
 | 
								printf("%s:\n", argv[i]);
 | 
				
			||||||
 | 
								list_directory(argv[i]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue