2025-02-28 18:48:30 +01:00
|
|
|
/* ************************************************************************** */
|
|
|
|
|
/* */
|
|
|
|
|
/* ::: :::::::: */
|
|
|
|
|
/* wildcard_exp.c :+: :+: :+: */
|
|
|
|
|
/* +:+ +:+ +:+ */
|
2025-03-08 17:32:47 +01:00
|
|
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
2025-02-28 18:48:30 +01:00
|
|
|
/* +#+#+#+#+#+ +#+ */
|
2025-03-06 17:37:08 +01:00
|
|
|
/* Created: 2025/02/23 15:02:59 by jguelen #+# #+# */
|
2025-03-19 17:20:03 +01:00
|
|
|
/* Updated: 2025/03/19 16:48:12 by jguelen ### ########.fr */
|
2025-02-28 18:48:30 +01:00
|
|
|
/* */
|
|
|
|
|
/* ************************************************************************** */
|
|
|
|
|
|
2025-03-06 12:45:05 +01:00
|
|
|
#include "ft_printf.h"
|
2025-02-28 18:48:30 +01:00
|
|
|
#include "subst.h"
|
2025-03-14 18:47:14 +01:00
|
|
|
#include "replace_substr.h"
|
2025-02-28 18:48:30 +01:00
|
|
|
|
2025-03-06 17:37:08 +01:00
|
|
|
/******************************************************************************/
|
2025-03-08 17:32:47 +01:00
|
|
|
/* NOTE: The use of errno and the setting of it was OKed by Alexandru in this */
|
2025-03-06 17:37:08 +01:00
|
|
|
/* context. */
|
|
|
|
|
/******************************************************************************/
|
2025-02-28 18:48:30 +01:00
|
|
|
/*
|
2025-03-06 17:37:08 +01:00
|
|
|
** Returns a directory stream corresponding to the current directory.
|
|
|
|
|
**
|
2025-02-28 18:48:30 +01:00
|
|
|
*/
|
2025-03-19 09:20:51 +01:00
|
|
|
static DIR *open_current_dir(void)
|
2025-03-06 17:37:08 +01:00
|
|
|
{
|
|
|
|
|
char *cur_dir_path;
|
|
|
|
|
size_t size;
|
|
|
|
|
DIR *dir;
|
|
|
|
|
|
|
|
|
|
size = PATH_SIZE_INIT;
|
|
|
|
|
cur_dir_path = malloc(size * sizeof(char));
|
|
|
|
|
if (!cur_dir_path)
|
|
|
|
|
return (NULL);
|
|
|
|
|
while (getcwd(cur_dir_path, size) == NULL)
|
|
|
|
|
{
|
|
|
|
|
if (errno != ERANGE)
|
|
|
|
|
return (NULL);
|
|
|
|
|
free(cur_dir_path);
|
|
|
|
|
size *= 2;
|
|
|
|
|
cur_dir_path = malloc(size * sizeof(char));
|
|
|
|
|
if (!cur_dir_path)
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
errno = 0;
|
|
|
|
|
dir = opendir(cur_dir_path);
|
|
|
|
|
free(cur_dir_path);
|
|
|
|
|
return (dir);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static t_wordlist *add_file_to_list(t_wordlist **list, char *filename)
|
|
|
|
|
{
|
|
|
|
|
t_worddesc *file_desc;
|
|
|
|
|
char *copy;
|
|
|
|
|
|
|
|
|
|
copy = ft_strdup(filename);
|
|
|
|
|
if (!copy)
|
|
|
|
|
return (wordlist_destroy(*list), NULL);
|
2025-03-10 17:17:02 +01:00
|
|
|
file_desc = worddesc_create(copy, '\0', NULL);
|
2025-03-06 17:37:08 +01:00
|
|
|
if (!file_desc)
|
|
|
|
|
{
|
|
|
|
|
wordlist_destroy(*list);
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
*list = wordlist_push(*list, file_desc);
|
|
|
|
|
return (*list);
|
|
|
|
|
}
|
2025-02-28 18:48:30 +01:00
|
|
|
|
2025-03-06 17:37:08 +01:00
|
|
|
/*
|
|
|
|
|
** A function designed to present all possible * or ? filename expansions
|
|
|
|
|
** for the current directory. (? is not asked by the subject).
|
2025-02-28 18:48:30 +01:00
|
|
|
** Does not take into account any other wildcard and does only search the
|
|
|
|
|
** current working directory.
|
|
|
|
|
** @PARAM A C compliant character string representing a pattern for a filename.
|
2025-03-08 17:32:47 +01:00
|
|
|
** @RETURN Returns a wordlist for which each entry corresponds to a filename
|
|
|
|
|
** that matches pattern->word if any file matches in the current directory.
|
|
|
|
|
** Otherwise return file_pattern itself if nothing matches the perceived
|
|
|
|
|
** pattern. This list should be alphabetically sorted.
|
2025-02-28 18:48:30 +01:00
|
|
|
*/
|
2025-03-10 17:17:02 +01:00
|
|
|
static t_wordlist *expand_star_core(t_worddesc *file_pattern)
|
2025-02-28 18:48:30 +01:00
|
|
|
{
|
2025-03-06 17:37:08 +01:00
|
|
|
struct dirent *new;
|
|
|
|
|
DIR *current_dir;
|
|
|
|
|
t_wordlist *file_wordlist;
|
|
|
|
|
|
|
|
|
|
current_dir = open_current_dir();
|
|
|
|
|
if (current_dir == NULL)
|
|
|
|
|
return (NULL);
|
|
|
|
|
file_wordlist = NULL;
|
2025-03-08 17:32:47 +01:00
|
|
|
errno = 0;
|
2025-03-06 17:37:08 +01:00
|
|
|
new = readdir(current_dir);
|
|
|
|
|
while (new)
|
|
|
|
|
{
|
|
|
|
|
if (fits_pattern(new->d_name, file_pattern))
|
|
|
|
|
{
|
|
|
|
|
if (add_file_to_list(&file_wordlist, new->d_name) == NULL)
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
errno = 0;
|
|
|
|
|
new = readdir(current_dir);
|
|
|
|
|
}
|
|
|
|
|
if (errno)
|
|
|
|
|
return (wordlist_destroy(file_wordlist), NULL);
|
|
|
|
|
if (!file_wordlist)
|
2025-03-08 17:32:47 +01:00
|
|
|
wordlist_push(file_wordlist, file_pattern);
|
2025-03-10 17:17:02 +01:00
|
|
|
return (wordlist_quicksort_full(file_wordlist));
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-15 15:44:23 +01:00
|
|
|
/*
|
|
|
|
|
** Returns 1 if and only if filename is recognized by pattern, 0
|
|
|
|
|
** otherwise or -1 in case of error.
|
|
|
|
|
** Takes only into account the * wildcard or ?, those characters
|
|
|
|
|
** NOTE: for a pattern to accept '.' as the first character of a filename
|
|
|
|
|
** it must be explicitly matched (only for the first character though).
|
|
|
|
|
** Similarly, '/' is never to be matched except if given explicitly.
|
|
|
|
|
*/
|
|
|
|
|
char fits_pattern(char *str, t_worddesc *pattern)
|
|
|
|
|
{
|
|
|
|
|
char **pattern_check;
|
|
|
|
|
size_t str_len;
|
|
|
|
|
size_t pattern_len;
|
|
|
|
|
size_t i;
|
|
|
|
|
char ret;
|
|
|
|
|
|
|
|
|
|
pattern_len = ft_strlen(pattern->word);
|
|
|
|
|
str_len = ft_strlen(str);
|
|
|
|
|
pattern_check = ft_calloc(str_len + 1, sizeof(char *));
|
|
|
|
|
if (!pattern_check)
|
|
|
|
|
return (-1);
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i <= str_len)
|
|
|
|
|
{
|
|
|
|
|
pattern_check[i] = ft_calloc(pattern_len + 1, sizeof(char));
|
|
|
|
|
if (!pattern_check[i])
|
2025-03-19 17:20:03 +01:00
|
|
|
return (destroy_pattern_check(pattern_check, str_len + 1), -1);
|
2025-03-15 15:44:23 +01:00
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
build_pattern_checks(str, pattern, pattern_check);
|
|
|
|
|
ret = pattern_check[str_len][pattern_len];
|
|
|
|
|
destroy_pattern_check(pattern_check, str_len + 1);
|
|
|
|
|
return (ret);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-10 17:17:02 +01:00
|
|
|
/*
|
|
|
|
|
** Returns NULL in case of error.
|
|
|
|
|
** NOTE: This phase of pre-processing relies partly on processing done before
|
|
|
|
|
** it therefore checks more loosely (and quote removal still seems not to be
|
|
|
|
|
** done on string comming from a variable expansion) <-----TO RE-CHECK
|
|
|
|
|
*/
|
|
|
|
|
t_wordlist *expand_star(t_worddesc *file_pattern)
|
|
|
|
|
{
|
|
|
|
|
size_t i;
|
|
|
|
|
char *tmp;
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (file_pattern->word[i])
|
|
|
|
|
{
|
|
|
|
|
if (file_pattern->marker[i] != '\'' && file_pattern->marker[i] != '"'
|
|
|
|
|
&& file_pattern->marker[i] != '&' && file_pattern->marker[i] != '$'
|
|
|
|
|
&& (file_pattern->word[i] == '\'' || file_pattern->word[i] == '"'))
|
|
|
|
|
{
|
|
|
|
|
tmp = replace_in_str(file_pattern->word, i, i, NULL);
|
|
|
|
|
free(file_pattern->word);
|
|
|
|
|
file_pattern->word = tmp;
|
|
|
|
|
tmp = replace_in_str(file_pattern->marker, i, i, NULL);
|
|
|
|
|
free(file_pattern->marker);
|
|
|
|
|
file_pattern->marker = tmp;
|
2025-03-10 17:22:38 +01:00
|
|
|
continue ;
|
2025-03-10 17:17:02 +01:00
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
return (expand_star_core(file_pattern));
|
2025-02-28 18:48:30 +01:00
|
|
|
}
|