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)
 | 
			
		||||
 | 
			
		||||
set(USERSPACE_PROJECTS
 | 
			
		||||
	Shell
 | 
			
		||||
	cat
 | 
			
		||||
	echo
 | 
			
		||||
	ls
 | 
			
		||||
	Shell
 | 
			
		||||
	test
 | 
			
		||||
	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