Hello,
I have been given this program to modify. The original program totals up files and directories in a file tree and has functions to detect the difference between them (whether they use / or .). I would like to modify it to use a linked list structure to create a copy of a file tree in memory.
The problem I'm having is that I'm having trouble understanding the original program. I thought it might be beneficial to comment the program first to break it up into smaller chunks.
Code:
/* du for file count
*
* show where the numerous files are
*/
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
// Function to generate the full name of a file or directory
// Declare pointers to root and name
char * fullname(const char *root, const char * name)
{
// A constant to hold the seperation character
const char * sep = "/";
// A pointer to res holding the result of the name, allocating memory based on length of component constants
char * res = (char *) malloc(strlen(root)+strlen(sep)+strlen(name)+1);
// Copy res into root
strcpy(res,root);
// Join parts of the name together
strcat(res,sep);
strcat(res,name);
// Return the result
return res;
}
// Function to detect full stops
int notdot (const char * s)
{
// Compare two strings for full stops
return strcmp(s,".") != 0 && strcmp(s,"..")!= 0 ;
}
// I don't understand this function, and the UNIX statements are foreign to me!
int issymlink(const char * name)
{
struct stat buf;
lstat(name, &buf);
return (buf.st_mode & S_IFMT) == S_IFLNK;
}
// Function to detect directories - again I don't understand, UNIX statements are foreign
int isdir(const char * name)
{
struct stat buf;
lstat(name, &buf);
return (buf.st_mode & S_IFMT) == S_IFDIR;
}
// Somehow count up number of names
int filecount( const char * dirname)
{
DIR *dd;
struct dirent *dp;
int res = 0;
dd = opendir( dirname );
assert(dd);
while ( (dp = readdir( dd )) )
if ( notdot(dp->d_name)){
char * name2 = fullname( dirname, dp->d_name);
if (issymlink(name2)) fprintf(stderr, "sym link %s\n", name2);
else if (isdir(name2)) res += filecount(name2);
else res ++;
}
printf("%10d %s\n",res, dirname);
closedir(dd);
return res;
}
// Wrap everything up and output number of files and directories
int main(int argc, char * argv[]) {
char * dirname = strdup(( argc >1) ? argv[1] : getenv("HOME"));
printf("%10d %s\n",filecount(dirname), dirname);
return (0);
}
Now, apart from those functions which I just don't understand (I use Windows and always have, but this program uses UNIX commands from what I can see):
1. char * fullname(const char *root, const char * name)
What is the difference between an asterisk directly before a name (*root) (which I know is a pointer) and one with a space between the asterisk and the name (char * fullname)?
2. I don't understand the issymlink function and the one that follows it. A structure seems to be defined, but what's its purpose?
3. The filecount function, there are a lot of functions, readdir, etc and pointers, *dd and *dp I've never seen before. I assume these are derived from the included dirent.h and assert.h files, so I'd need to look at those to work out what's going on?
I've worked out that basically I need to replace the constants and variables that are being used at the moment (and the pointers and other stuff (see Q1), define a new structure for the file tree (which I've been provided with, see below) and then change the references to the original pointers and stuff to those in the new structure. I'm pretty sure I could probably do that using net references and examples of linked lists, but not understand the program in its original form means I'm struggling to work out what I can remove and what are actual vital functions.
The structure I'll be replacing and modifying references to point to it is:
Code:
enum Tnodetype {n_file, n_directory, n_symlink};
typedef enum Tnodetype Nodetype;
struct Tcell{
struct Tcell *next;
char * localname;
char * fullname;
struct Tcell * content; // list of files in directory
Nodetype nodetype;
};
typedef struct Tcell Cell, *List;
localname is the name within this directory, e.g. ddd.c
fullname is the full pathname for this file e.g. /home/staff/jrl/source/c/ddd.c
nodetype is the type of this entry
for a directory,content is a list of files in the directory
BTW, likewise here:
4. Are n_file, n_directory and n_symlink variables of the enum type Tnodetype?
5. I understand the structure Tcell as the actual node for the linked list, but what is Nodetype nodetype? What is Nodetype that has nodetype as an instance of itself? Is Nodetype an offset of TNodetype?
6. And why, after the struct Tcell has been declared does it re-declare a typedef struct Tcell?
I'm sorry if this is a bit much or if it's overly simple. I thought trying to break it down would help, but it seems to have left me even more confused.
Thanks for any insight you can give me. I'm happy to read any pages/texts that you would recommend if you feel that would be useful.
Thanks.
Hussein.