Reputation: 73
I'm working to create a function that takes in a path and reads all the files within it and creates a linked lists. Reading the directory works well but I'm having difficulty creating and storing the relevant information in a linked list for use later.
Heres the structure I'm using currently:
typedef struct searchPool searchPool;
struct searchPool{
char * path;
char * fileName;
char *pathFile;
searchPool * next;
};
The function to create a new element of the type 'SearchPool' is defined as such:
searchPool * mallocStructPool (char * path, char * fileName, char * filePath ) {
searchPool * element = (searchPool*)malloc(sizeof(searchPool));
element->path = malloc(sizeof(char * ));
element->fileName = malloc(sizeof(char * ));
element->pathFile = malloc(sizeof(char * ));
element->path = path;
element->fileName = fileName;
element->pathFile = filePath;
element->next = NULL;
return element;
}
Finally the recursive function that take the list's head is written as such (code commented if you scroll to the right):
void listDir(char * path, searchPool * head){
DIR * d = opendir(path); // open the path
searchPool * element; // create new Element of type SearchPool
struct dirent * dir; // for the directory entries
while ((dir = readdir(d)) != NULL) { // if we were able to read somehting from the directory
if(dir-> d_type != DT_DIR) { // if the type is not directory just print it with blue
char * s = malloc(sizeof(char*)+1); // variable to concatenate
s = concat(path, dir->d_name); // concatenate path and filename together
//printf("%s\n",s);
element = mallocStructPool(dir->d_name, path, s); // malloc new element and set variables
head->next = element;
element->next = NULL;
free(s);
} else
if(dir -> d_type == DT_DIR && strcmp(dir->d_name,".")!=0 && strcmp(dir->d_name,"..")!=0 ) {// if it is a directory
char d_path[255]; // here I am using sprintf which is safer than strcat
sprintf(d_path, "%s/%s", path, dir->d_name);
listDir(d_path, element); // recall with the new path
}
}
closedir(d); // finally close the directory
}
The problem is that when the function listDir() is called it only ends up printing the first path that I give it in it's parameters and the rest is ignored. Do I have to return the new element in listDir() after each run? I don't see where I'm going wrong.
Any help is appreciated. Thanks for your time.
Upvotes: 1
Views: 173
Reputation: 6404
To add an element to the tail
searchPool *ptr;
searchPool *prev = 0;
searchPool *head = something;
for(ptr = head; ptr != NULL; ptr = ptr->next)
prev = ptr;
element->next = 0;
prev->next = element;
To add to the head (faster)
element->next = head;
head = element;
Note head is not stable now.
To add one after the head
element->next = head->next;
head->next = element
Note that head is now probably a dummy node without any data in it, which exists for the sake of having a stable and constant "head" pointer to the linked list;
Upvotes: 0
Reputation: 26717
Your code don't make sense. You don't need to allocate a struct and his members. Plus don't cast the return of malloc. You don't check the return of malloc()
. And you don't copy the strings.
In your second function you should return the linked list and check return function of opendir()
.
Here a example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
typedef struct searchPool searchPool;
struct searchPool {
char *path;
char *fileName;
char *pathFile;
searchPool *next;
};
static searchPool *mallocStructPool(char *path, char *fileName) {
searchPool *element = malloc(sizeof *element);
if (element == NULL) {
goto error;
}
size_t path_size = strlen(path);
element->path = malloc(path_size + 1);
if (element->path == NULL) {
goto free_element;
}
size_t fileName_size = strlen(fileName);
element->fileName = malloc(fileName_size + 1);
if (element->fileName == NULL) {
goto free_path;
}
element->pathFile = malloc(path_size + 1 + fileName_size + 1);
if (element->pathFile == NULL) {
goto free_fileName;
}
memcpy(element->path, path, path_size);
element->path[path_size] = '\0';
memcpy(element->fileName, fileName, fileName_size);
element->fileName[fileName_size] = '\0';
memcpy(element->pathFile, path, path_size);
element->pathFile[path_size] = '/';
memcpy(element->pathFile + path_size + 1, fileName, fileName_size);
element->pathFile[path_size + 1 + fileName_size] = '\0';
return element;
free_fileName:
free(element->fileName);
free_path:
free(element->path);
free_element:
free(element);
error:
return NULL;
}
searchPool *listDir(char *path);
static searchPool *listDir_aux(char *path, struct dirent *dirent) {
if (dirent->d_type == DT_DIR && dirent->d_type != DT_LNK &&
strcmp(dirent->d_name, ".") != 0 && strcmp(dirent->d_name, "..") != 0) {
size_t path_size = strlen(path);
size_t name_size = strlen(dirent->d_name);
char *d_path = malloc(path_size + 1 + name_size + 1);
if (d_path == NULL) {
return NULL;
}
memcpy(d_path, path, path_size);
d_path[path_size] = '/';
memcpy(d_path + path_size + 1, dirent->d_name, name_size);
d_path[path_size + 1 + name_size] = '\0';
searchPool *ret = listDir(d_path);
free(d_path);
return ret;
}
return mallocStructPool(path, dirent->d_name);
}
searchPool *listDir(char *path) {
printf("%s\n", path);
DIR *dir = opendir(path);
if (dir == NULL) {
perror("dir()");
return NULL;
}
searchPool *head = NULL;
struct dirent *dirent;
while ((dirent = readdir(dir)) != NULL) {
searchPool *elem = listDir_aux(path, dirent);
if (elem != NULL) {
elem->next = head;
head = elem;
}
}
closedir(dir);
return head;
}
int main(void) {
searchPool *head = listDir("/tmp");
searchPool *tmp;
for (searchPool *elem = head; elem != NULL; elem = tmp) {
printf("%s, %s, %s\n", elem->path, elem->fileName, elem->pathFile);
free(elem->path);
free(elem->fileName);
free(elem->pathFile);
tmp = elem->next;
free(elem);
}
}
Upvotes: 3