ls finish, need more test

This commit is contained in:
Xamora 2025-01-10 09:12:14 +01:00
parent 411659db94
commit 69aefc764d
21 changed files with 612 additions and 58 deletions

View file

@ -7,3 +7,5 @@
-iquoteinc -iquoteinc
-iquotelib -iquotelib
-g -g
-D_POSIX_C_SOURCE=200809L
-D_DEFAULT_SOURCE

View file

@ -1,6 +1,13 @@
#pragma once #pragma once
#include <inttypes.h> #include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <sys/ioctl.h>
typedef struct { typedef struct {
bool l; bool l;
@ -8,8 +15,43 @@ typedef struct {
bool R; bool R;
bool r; bool r;
bool t; bool t;
bool dashdash;
int error[2]; int error[2];
} flags_t; } flags_t;
flags_t get_flags(char **argv); typedef struct {
void display_flags(flags_t flags); DIR *dir;
char *path;
char *name;
bool is_file;
struct stat stat;
struct stat lstat;
struct passwd *psswd;
struct group *grp;
} dir_t;
extern flags_t flags;
extern struct winsize win;
// Parsing
void get_flags(char **argv);
void parsing(char **argv, t_list ***files, t_list ***dirs, i32 *max_size, i32 *len, i32 *error);
dir_t *get_directory_files(char *path);
// Display
void display_name(dir_t *dir);
void display_file(dir_t *dir, i32 max_size);
i32 display_files(t_list **files);
void display_directory(dir_t *dir);
i32 display_files_stat(t_list **files);
void display_single_stat(dir_t *dir, i32 max_size);
void space_between_files(t_list **files, dir_t *file);
// Directory
void strmode(mode_t mode, char *buf);
void delete_directory(void *content);
t_list **get_all_in(dir_t *dir);
void add_sort(t_list **head, dir_t *new_dir, bool file_priority);
// Free
void free_files(t_list **files);

View file

@ -69,7 +69,7 @@ u32 ft_printf(const char *str, ...)
{ {
va_list args; va_list args;
va_start(args, str); va_start(args, str);
u32 count = ft_vdprintf(0, str, args); u32 count = ft_vdprintf(1, str, args);
va_end(args); va_end(args);
return count; return count;
} }

View file

@ -0,0 +1,25 @@
#include "libft.h"
static void delete(t_list **deleted, void (*del)(void*));
void ft_lstremove_back(t_list **lst, void (*del)(void*))
{
if (lst == nullptr || del == nullptr)
return;
if ((*lst)->next == nullptr)
return delete(lst, del);
t_list *cur = *lst;
while (cur->next != nullptr && cur->next->next != nullptr)
cur = cur->next;
delete(&(cur->next), del);
}
static void delete(t_list **deleted, void (*del)(void*)) {
del(*deleted);
free(*deleted);
*deleted = nullptr;
}

View file

@ -0,0 +1,13 @@
#include "libft.h"
void ft_lstremove_front(t_list **lst, void (*del)(void*))
{
if (lst == nullptr || del == nullptr)
return;
t_list *next = (*lst)->next;
del(*lst);
free(*lst);
*lst = next;
}

View file

@ -17,8 +17,8 @@ u32 ft_putnbr_fd(i64 n, int fd)
if (n < 0) if (n < 0)
ft_putchar_fd('-', fd); ft_putchar_fd('-', fd);
n = ABS(n); n = ABS(n);
int len = ft_get_size(n) + 1; int len = ft_get_size(n);
while (--len > 1) while (--len > 0)
ft_putchar_fd(n / ft_power(10, len) % 10 + 48, fd); ft_putchar_fd(n / ft_power(10, len) % 10 + 48, fd);
ft_putchar_fd(n % 10 + 48, fd); ft_putchar_fd(n % 10 + 48, fd);
return ft_get_size(n); return ft_get_size(n);

6
lib/libft/ft_strcat.c Normal file
View file

@ -0,0 +1,6 @@
#include "libft.h"
char *ft_strcat(char *dest, const char *src) {
ft_strcpy(dest + ft_strlen(dest), src);
return dest;
}

7
lib/libft/ft_strcmp.c Normal file
View file

@ -0,0 +1,7 @@
i32 ft_strcmp(const char *s1, const char *s2) {
i32 i = 0;
for (; s1[i] != '\0' && s2[i] != '\0'; i++)
if (s1[i] != s2[i])
return s1[i] - s2[i];
return s1[i] - s2[i];
}

11
lib/libft/ft_strcpy.c Normal file
View file

@ -0,0 +1,11 @@
#include "libft.h"
char *ft_strcpy(char *dest, const char *src) {
while (*src) {
char c = *src++;
*dest++ = c;
if (c == '\0')
return dest;
}
return dest;
}

View file

@ -14,8 +14,7 @@
size_t ft_strlcat(char *dest, const char *src, size_t size) size_t ft_strlcat(char *dest, const char *src, size_t size)
{ {
size_t len_dest; size_t len_dest, len_src;
size_t len_src;
if (size == 0) if (size == 0)
return (ft_strlen(src)); return (ft_strlen(src));

19
lib/libft/ft_strlcats.c Normal file
View file

@ -0,0 +1,19 @@
#include "libft.h"
char *ft_strlcats(u32 nbr_str, ...) {
va_list args;
u32 len = 0;
va_start(args, nbr_str);
for (u32 i = 0; i < nbr_str; i++)
len += ft_strlen(va_arg(args, char *));
va_end(args);
va_start(args, nbr_str);
char *new_str = ft_calloc(len + 1, sizeof(char));
for (u32 i = 0; i < nbr_str; i++)
ft_strcat(new_str, va_arg(args, char *));
va_end(args);
return new_str;
}

View file

@ -12,19 +12,14 @@
#include "libft.h" #include "libft.h"
size_t ft_strlcpy(char *dest, const char *src, size_t size) u32 ft_strlcpy(char *dest, const char *src, u32 size)
{ {
size_t i; if (!size)
return (ft_strlen(src));
i = 0; u32 i = 0;
if (size) for (; i < size && src[i] != '\0'; i++)
{
while (i < size - 1 && src[i] != '\0')
{
dest[i] = src[i]; dest[i] = src[i];
i++;
}
dest[i] = '\0'; dest[i] = '\0';
}
return (ft_strlen(src)); return (ft_strlen(src));
} }

View file

@ -24,7 +24,7 @@ char *ft_substr(char const *s, unsigned int start, size_t len)
size = 0; size = 0;
else if ((unsigned long)size > len) else if ((unsigned long)size > len)
size = len; size = len;
new_s = malloc(size + 1); new_s = ft_calloc(size + 2, 1);
if (new_s == NULL) if (new_s == NULL)
return (NULL); return (NULL);
if (start <= ft_strlen(s)) if (start <= ft_strlen(s))

View file

@ -16,6 +16,7 @@
# include <unistd.h> # include <unistd.h>
# include <stdint.h> # include <stdint.h>
# include <inttypes.h> # include <inttypes.h>
# include <stdarg.h>
typedef struct s_list typedef struct s_list
{ {
@ -52,12 +53,16 @@ void *ft_memcpy(void *dest, const void *src, size_t s);
void *ft_memmove(void *dest, const void *src, size_t s); void *ft_memmove(void *dest, const void *src, size_t s);
void *ft_memchr(const void *memory_block, int searched_char, size_t size); void *ft_memchr(const void *memory_block, int searched_char, size_t size);
int ft_memcmp(const void *pointer1, const void *pointer2, size_t size); int ft_memcmp(const void *pointer1, const void *pointer2, size_t size);
size_t ft_strlcpy(char *dest, const char *src, size_t size); char *ft_strcpy(char *dest, const char *src);
u32 ft_strlcpy(char *dest, const char *src, u32 size);
char *ft_strnstr(const char *big, const char *little, size_t len); char *ft_strnstr(const char *big, const char *little, size_t len);
char *ft_strchr(const char *str, int search); char *ft_strchr(const char *str, int search);
char *ft_strrchr(const char *str, int search); char *ft_strrchr(const char *str, int search);
i32 ft_strcmp(const char *s1, const char *s2);
int ft_strncmp(const char *s1, const char *s2, size_t n); int ft_strncmp(const char *s1, const char *s2, size_t n);
char * ft_strcat(char *dest, const char *src);
size_t ft_strlcat(char *dest, const char *src, size_t size); size_t ft_strlcat(char *dest, const char *src, size_t size);
char *ft_strlcats(u32 nbr_str, ...);
char *ft_strdup(const char *src); char *ft_strdup(const char *src);
int ft_atoi(const char *nptr); int ft_atoi(const char *nptr);
char **ft_split(char const *s, char c); char **ft_split(char const *s, char c);
@ -76,12 +81,14 @@ char *ft_strtrim(char const *s1, char const *set);
char *ft_substr(char const *s, unsigned int start, size_t len); char *ft_substr(char const *s, unsigned int start, size_t len);
t_list *ft_lstnew(void *content); t_list *ft_lstnew(void *content);
void ft_lstadd_front(t_list **lst, t_list *new); void ft_lstadd_front(t_list **lst, t_list *new);
void ft_lstadd_back(t_list **lst, t_list *new);
int ft_lstsize(t_list *lst); int ft_lstsize(t_list *lst);
t_list *ft_lstlast(t_list *lst); t_list *ft_lstlast(t_list *lst);
void ft_lstadd_back(t_list **lst, t_list *new);
void ft_lstdelone(t_list *lst, void (*del)(void*)); void ft_lstdelone(t_list *lst, void (*del)(void*));
void ft_lstclear(t_list **lst, void (*del)(void*)); void ft_lstclear(t_list **lst, void (*del)(void*));
void ft_lstiter(t_list *lst, void (*f)(void *)); void ft_lstiter(t_list *lst, void (*f)(void *));
t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *));
void ft_lstremove_front(t_list **lst, void (*del)(void*));
void ft_lstremove_back(t_list **lst, void (*del)(void*));
int ft_atoi_check(const char *nptr); int ft_atoi_check(const char *nptr);
u32 ft_strslen(char **strs); u32 ft_strslen(char **strs);

102
src/directory.c Normal file
View file

@ -0,0 +1,102 @@
void
strmode(mode_t mode, char *buf) {
const char chars[] = "rwxrwxrwx";
for (size_t i = 0; i < 9; i++)
buf[i] = (mode & (1 << (8-i))) ? chars[i] : '-';
buf[9] = '\0';
}
void
delete_directory(void *deleted) {
t_list *lst = (t_list*)deleted;
dir_t *dir = (dir_t*)lst->content;
free(dir->path);
free(dir);
}
void
remove_all_end_character(char *str, char c) {
for (i32 i = ft_strlen(str) - 1; i >= 0; i--) {
if (str[i] != c)
return;
str[i] = '\0';
}
}
t_list **
get_all_in(dir_t *dir) {
struct dirent *in_dir;
t_list **head = ft_calloc(1, sizeof(t_list*));
while ((in_dir = readdir(dir->dir)) != nullptr) {
if (!flags.a && ft_strncmp(".", in_dir->d_name, 1) == 0)
continue;
remove_all_end_character(dir->path, '/');
char *new_path = ft_strlcats(3, dir->path, "/", in_dir->d_name);
dir_t *new_dir = get_directory_files(new_path);
free(new_path);
if (!new_dir)
continue;
new_dir->name = in_dir->d_name;
if (ft_strcmp(new_dir->name, "switchpro_rstick_click_md.png") == 0)
ft_printf("");
add_sort(head, new_dir, false);
}
return head;
}
static bool compare_name(char *s1, char *s2);
static bool compare_time(dir_t *dir1, dir_t *dir2);
void
add_sort(t_list **head, dir_t *new_dir, bool file_priority) {
t_list *cur = *head, *prev = NULL;
for (; cur != nullptr; prev = cur, cur = cur->next) {
dir_t *cur_dir = ((dir_t *)cur->content);
if (file_priority && !cur_dir->is_file && new_dir->is_file)
break;
else if (file_priority && cur_dir->is_file && !new_dir->is_file)
continue;
if (flags.t) {
if (compare_time(new_dir, cur_dir))
break;
}
else
if (compare_name(new_dir->name, cur_dir->name))
break;
}
t_list *new = ft_lstnew(new_dir);
if (!prev)
*head = new;
else
prev->next = new;
new->next = cur;
}
static bool compare_name(char *s1, char *s2) {
i32 cmp = ft_strcmp(s1, s2);
if ((flags.r && cmp > 0) || (!flags.r && cmp < 0))
return true;
return false;
}
static bool compare_time(dir_t *dir1, dir_t *dir2) {
time_t dir1_sec = dir1->lstat.st_mtim.tv_sec;
time_t dir2_sec = dir2->lstat.st_mtim.tv_sec;
time_t dir1_nsec = dir1->lstat.st_mtim.tv_nsec;
time_t dir2_nsec = dir2->lstat.st_mtim.tv_nsec;
i64 diff_sec = dir1_sec - dir2_sec;
i64 diff_nsec = dir1_nsec - dir2_nsec;
if (diff_sec == 0 && diff_nsec == 0) {
if (compare_name(dir1->name, dir2->name))
return true;
}
else if ((flags.r && (diff_sec < 0 || (diff_sec == 0 && diff_nsec < 0))) ||
(!flags.r && (diff_sec > 0 || (diff_sec == 0 && diff_nsec > 0))))
return true;
return false;
}

96
src/display.c Normal file
View file

@ -0,0 +1,96 @@
static void display_recursive(dir_t *dir);
void space_between_files(t_list **files, dir_t *file) {
if (win.ws_col == 0) {
ft_printf("\n");
return;
}
u32 max = 0, i = 0, index_file = 0;
for (t_list *cur = *files; cur != nullptr; cur = cur->next) {
dir_t *cur_file = (dir_t*)(cur)->content;
max = MAX(ft_strlen(cur_file->name), max);
if (ft_strcmp(cur_file->name, file->name) == 0)
index_file = i;
i++;
}
u32 col = MAX(win.ws_col / max, 1);
u32 cal = index_file % col;
if (col >= i && index_file != i - 1)
ft_printf(" ");
else if (col >= i && index_file == i - 1)
ft_printf("\n");
else if (cal == col - 1 || index_file == i - 1)
ft_printf("\n");
else
for (i = 0; i < max - ft_strlen(file->name) + 1; i++)
ft_printf(" ");
}
void
display_name(dir_t *dir) {
ft_printf("%s", dir->name);
}
void
display_directory(dir_t *dir) {
if (flags.R) {
if (!dir->is_file)
display_recursive(dir);
}
else {
t_list **files = get_all_in(dir);
display_files(files);
free_files(files);
}
}
i32
display_files(t_list **files) {
i32 drawed = 0;
if (flags.l)
return display_files_stat(files);
else {
for (t_list *cur = *files; cur != nullptr; cur = cur->next) {
dir_t *dir = (dir_t*)(cur)->content;
display_name(dir);
drawed++;
if (cur->next != nullptr)
space_between_files(files, dir);
}
if (drawed > 0)
ft_printf("\n");
}
return drawed;
}
static void
to_print_return_of_line() {
static int need_to_return_of_line = 0;
if (!need_to_return_of_line)
need_to_return_of_line = 1;
else {
ft_printf("\n");
}
}
static void
display_recursive(dir_t *dir) {
if (dir->is_file)
return;
to_print_return_of_line();
ft_printf("%s:\n", dir->path);
t_list **files = get_all_in(dir);
display_files(files);
for (t_list *cur = *files; cur != nullptr; cur = cur->next) {
dir_t *cur_dir = (dir_t*)cur->content;
if (!cur_dir->is_file
&& ft_strcmp(".", cur_dir->name) != 0
&& ft_strcmp("..", cur_dir->name) != 0)
display_recursive(cur_dir);
}
free_files(files);
}

129
src/display_stat.c Normal file
View file

@ -0,0 +1,129 @@
static void display_type(dir_t *dir);
static void display_permission(dir_t *dir);
static void display_size(dir_t *dir, i32 max_size);
static void display_date(dir_t *dir);
static void display_path(dir_t *dir);
i32
display_files_stat(t_list **files) {
if (!files)
return 0;
if (ft_lstsize(*files) <= 0) {
ft_printf("total 0\n");
return 0;
}
i32 max_size = ft_get_size(((dir_t*)(*files)->content)->lstat.st_size);
i32 total = 0;
t_list *cur;
for (cur = *files; cur != nullptr; cur = cur->next) {
dir_t *dir = (dir_t*)(cur)->content;
max_size = MAX(ft_get_size(dir->lstat.st_size), max_size);
total += dir->lstat.st_blocks;
}
ft_printf("total %d\n", total / 2);
i32 drawed = 0;
for (cur = *files; cur != nullptr; cur = cur->next) {
dir_t *dir = (dir_t*)(cur)->content;
display_single_stat(dir, max_size);
drawed++;
ft_printf("\n");
}
return drawed;
}
void
display_single_stat(dir_t *dir, i32 max_size) {
if (!dir)
return;
display_type(dir);
display_permission(dir);
ft_printf(" ");
ft_printf("%d", dir->lstat.st_nlink);
ft_printf(" ");
if (dir->psswd)
ft_printf("%s", dir->psswd->pw_name);
ft_printf(" ");
if (dir->grp)
ft_printf("%s", dir->grp->gr_name);
ft_printf(" ");
display_size(dir, max_size);
ft_printf(" ");
display_date(dir);
ft_printf(" ");
display_name(dir);
if (S_ISLNK(dir->lstat.st_mode))
display_path(dir);
}
static void
display_type(dir_t *dir) {
if (!dir)
return;
if (S_ISLNK(dir->lstat.st_mode))
ft_printf("l");
else if (!dir->is_file)
ft_printf("d");
else if (S_ISSOCK(dir->lstat.st_mode))
ft_printf("s");
else if (S_ISFIFO(dir->lstat.st_mode))
ft_printf("p");
else if (S_ISCHR(dir->lstat.st_mode))
ft_printf("c");
else if (S_ISBLK(dir->lstat.st_mode))
ft_printf("b");
else
ft_printf("-");
}
static void
display_permission(dir_t *dir) {
if (!dir)
return;
char buf[10];
strmode(dir->stat.st_mode, buf);
ft_printf("%s", buf);
}
static void
display_size(dir_t *dir, i32 max_size) {
if (!dir)
return;
i32 len = ft_get_size(dir->lstat.st_size);
for (int i = max_size - len; i > 0; i--)
ft_printf(" ");
ft_printf("%d", dir->lstat.st_size);
}
static void
display_date(dir_t *dir) {
if (!dir)
return;
struct timespec last_edit = dir->lstat.st_mtim;
char *base_time_str = ctime(&last_edit.tv_sec);
if (!base_time_str)
return;
char *time_str = ft_substr(base_time_str, 4, ft_strlen(base_time_str) - 14);
if (!time_str)
return;
ft_printf(time_str);
free(time_str);
}
static void
display_path(dir_t *dir) {
if (!dir || !dir->path)
return;
char buf[512] = {[0 ... 511] = 0};
i32 error = readlink(dir->path, buf, dir->lstat.st_size);
if (error == -1)
return;
ft_printf(" -> %s", buf);
}

15
src/free.c Normal file
View file

@ -0,0 +1,15 @@
void
free_files(t_list **files) {
for (t_list *cur = *files; cur != nullptr;) {
dir_t *file = (dir_t*)cur->content;
if (!file->is_file)
closedir(file->dir);
free(file->path);
free(file);
t_list *next = cur->next;
free(cur);
cur = next;
}
free(files);
}

View file

@ -1,17 +1,48 @@
int main(int argc, char **argv) { flags_t flags = {false, false, false, false, false, false,
{-1, -1}};
struct winsize win;
if (argc < 2) int
return 1; main(int argc, char **argv) {
flags_t flags = get_flags(argv); if (argc > 1) {
get_flags(argv);
if (flags.error[0] != -1) { if (flags.error[0] != -1) {
ft_printf_fd(2, "ls: invalid line width: \'%s\'", ft_printf_fd(2, "ft_ls: invalid option -- \'%s\'\n",
&argv[flags.error[0]][flags.error[1]]); &argv[flags.error[0]][flags.error[1]]);
return 2; return 2;
} }
display_flags(flags); }
//ft_ls(flags); ioctl(STDOUT_FILENO, TIOCGWINSZ, &win);
errno = 0;
return 0; t_list **files = ft_calloc(ft_strslen(argv) + 1, sizeof(t_list*));
t_list **dirs = ft_calloc(ft_strslen(argv) + 1, sizeof(t_list*));
i32 max_size = 0, len = 0, error = 0;
parsing(argv, &files, &dirs, &max_size, &len, &error);
if (len == 0 && error == 0)
add_sort(dirs, get_directory_files("."), true);
i32 left = len;
if (ft_lstsize(*files) > 0)
left -= display_files(files);
free_files(files);
if (left != len && left > 0)
ft_printf("\n");
for (t_list *cur = *dirs; cur != nullptr; cur = cur->next) {
dir_t *dir = (dir_t*)cur->content;
if (len > 1 && !flags.R)
ft_printf("%s:\n", dir->path);
display_directory(dir);
if (left > 1)
ft_printf("\n");
left--;
}
free_files(dirs);
return error;
} }

View file

@ -1,10 +1,10 @@
flags_t get_flags(char **argv) { void
flags_t flags = {false, false, false, false, false, get_flags(char **argv) {
{-1, -1}}; for (i32 i = 1; argv[i] != nullptr; i++) {
if (ft_strcmp(argv[i], "--") == 0)
for (int i = 1; argv[i] != NULL; i++) { return;
if (argv[i][0] == '-') { if (argv[i][0] == '-') {
for (int j = 1; argv[i][j] != '\0'; j++) { for (i32 j = 1; argv[i][j] != '\0'; j++) {
if (argv[i][j] == 'l') if (argv[i][j] == 'l')
flags.l = true; flags.l = true;
else if (argv[i][j] == 'a') else if (argv[i][j] == 'a')
@ -18,27 +18,82 @@ flags_t get_flags(char **argv) {
else { else {
flags.error[0] = i; flags.error[0] = i;
flags.error[1] = j; flags.error[1] = j;
return flags;
return ;
} }
} }
} }
} }
return flags;
}
void display_flags(flags_t flags) {
ft_printf("l: %b; a: %b; R: %b; r: %b; t: %b\n",
flags.l, flags.a, flags.R, flags.r, flags.t);
}
char **get_files(char **argv) {
char **files = ft_calloc(ft_strslen(argv), sizeof(char*));
for (int i = 1; argv[i] != NULL; i++) {
if (argv[i][0] == '-') {
}
}
} }
void
parsing(char **argv, t_list ***files, t_list ***dirs, i32 *max_size, i32 *len, i32 *error) {
for (i32 i = 0; argv[i + 1] != nullptr; i++) {
if (ft_strcmp(argv[i + 1], "--") == 0) {
flags.dashdash = true;
continue;
}
dir_t *dir = get_directory_files(argv[i + 1]);
if (dir != nullptr) {
(*len)++;
if (dir->is_file) {
*max_size = MAX(ft_get_size(dir->lstat.st_size), *max_size);
add_sort(*files, dir, true);
}
else
add_sort(*dirs, dir, true);
}
else if (errno > 0)
*error = 2;
}
flags.dashdash = false;
}
static void*
free_dir_return_null(dir_t *dir) {
free(dir->path);
free(dir);
return nullptr;
}
dir_t *
get_directory_files(char *path) {
dir_t *dir = nullptr;
if (!flags.dashdash)
if (path[0] == '-' && ft_strlen(path) != 1)
return nullptr;
dir = ft_calloc(1, sizeof(dir_t));
dir->path = ft_strdup(path);
dir->name = dir->path;
stat(path, &dir->stat);
lstat(path, &dir->lstat);
dir->psswd = getpwuid(dir->stat.st_uid);
if (!dir->psswd)
return free_dir_return_null(dir);
dir->grp = getgrgid(dir->psswd->pw_gid);
if (!dir->grp)
return free_dir_return_null(dir);
if (S_ISLNK(dir->lstat.st_mode)) {
dir->is_file = true;
return dir;
}
dir->dir = opendir(path);
if (dir->dir == nullptr) {
if (errno == EACCES)
ft_printf_fd(2, "Permission denied\n");
else if (errno == ENOENT)
ft_printf_fd(2, "ft_ls: cannot access '%s': No such file or directory\n", path);
else if (errno == ENOTDIR) {
dir->is_file = true;
return dir;
}
return free_dir_return_null(dir);
}
return dir;
}