I am trying to create a linked list data structure that will allow me to store the Group ID # as well as the file path to a file's directory that it belongs to. This program opens up the current directory and gets all the regular files from the current directory, it outputs each file's path, and attempts to insert the paths into a linked list. For each file path that it inserts, a new groupID will be created (adding 1 to whatever the previous groupID # was), starting at 1 for the first groupID. Here is my code for it so far:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
typedef struct FileGroups
{
int groupID;
char *path;
struct FileGroups* next;
} FileGroups;
FileGroups *head;
void insert(char *path)
{
FileGroups *temp;
temp = (FileGroups*)malloc(sizeof(FileGroups));
temp->groupID += 1;
temp->path = path;
temp->next = head;
head = temp;
temp = temp ->next;
}
void print()
{
FileGroups *temp;
temp = head;
printf("\nLinked list: \n");
while(temp!=NULL)
{
printf("%d %s\n", temp->groupID, temp->path);
temp = temp->next;
}
}
void listFilesRecursively(const char *basePath)
{
char path[1024];
struct dirent *dp;
DIR *dir = opendir(basePath);
if (!dir)
{
return;
}
while ((dp = readdir(dir)) != NULL)
{
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
{
struct stat sb;
strcpy(path, basePath);
strcat(path, "/");
strcat(path, dp->d_name);
if(stat(path, &sb) == 0 && S_ISREG(sb.st_mode))
{
printf("%s\n", path);
insert(path);
}
else
{
return;
}
}
}
closedir(dir);
}
int main()
{
listFilesRecursively(".");
print();
return 0;
}
When I go to print out the linked list, I get the following as output:
On the top half you can see all the regular files that are within my current directory and below is my linked list which seems to only store the last file listed in my current directory and also to the left we see that the groupID # is also unchanged instead of adding 1 with each file path added, it is stuck at groupID #1. Any suggestions or pointers on where I'm going wrong would be greatly appreciated. Thanks!
At each iteration path
is overwritten and assigned to the new element of the list, but you're not copying the string to a new buffer.
Therefore at the end each element of the list will point to the path
declared in listFilesRecursively()
, which will contain only the last file listed
...
int GroupID = 1;
void listFilesRecursively(const char *basePath)
...
char path[1024];
...
// Here path is overwritten
strcpy(path, basePath);
strcat(path, "/");
strcat(path, dp->d_name);
...
insert(path);
void insert(char *path)
...
// This is copying only the pointer to path
temp->path = path;
You should allocate a new buffer for path upon insertion.
void insert(char *path)
{
FileGroups *temp;
temp = (FileGroups*)malloc(sizeof(FileGroups));
/**
* This should not be += 1
* Memory allocated by malloc is not initialised.
* Value at these locations are indeterminate.
*
* To know the next groupID I'm using a simple
* global variable as suggested by Serge Ballesta
* in his comment
*/
temp->groupID = GroupID++;
//------------------------------------------------------
temp->path = malloc(strlen(path)*sizeof(char));
strcpy(temp->path, path);
//------------------------------------------------------
temp->next = head;
head = temp;
temp = temp ->next;
}
You can run it here https://onlinegdb.com/O6cTm7Hu1
About malloc()
Is malloc() initializing allocated array to zero?