I've been tasked with remaking a portion of the functionality of the find command. The first part I'm trying to do is just the normal "find " where it lists all files and sub-directories within that directory. I'm using the actual find command to test my results.
Anything apparent that I'm missing that's causing me to print improper file paths?
Image Order:
C Code
Expected Output
Actual Output
Tree for the directory I'm using to test
void readSub (char* subDir) { DIR *sub_dp = opendir(subDir); //Opens directory stream struct dirent *subDirp; //define sub directory pointer struct stat buf; //define file status struct char t1[] = "."; char t2[] = ".."; char t3[] = "/"; if(sub_dp != NULL) // Was directory successfully opened { //read each entry one time only while((subDirp = readdir(sub_dp)) != NULL) { char *temp = subDirp -> d_name; //check if first entry was a sub directory //avoid searching for . and .. if(strcmp(temp, t1) != 0 && strcmp(temp, t2) != 0) { char *tempSub = t3; tempSub = strcat(tempSub, temp); //add / to entry name char *temp_full_path = malloc(sizeof(char) * 2000); temp_full_path = strcpy(temp_full_path, subDir); strcat(temp_full_path, tempSub); //gives full path printf("%s\n", temp_full_path); DIR *subsubDP = opendir(temp_full_path); //try to open if(subsubDP != NULL) //if not NULL then subsubDP is sub directory { closedir(subsubDP); //will get opened in recursive call readSub(temp_full_path); //recursive call } } } //end of while loop closedir(sub_dp); //close directory stream } else { printf("Can't open directory\n"); exit(2); } } int main(int argc, char **argv) { char *dir; if(argc < 2) { dir = "."; } else { dir = argv[1]; } readSub(dir); exit(0); }
CodePudding user response:
The problem is
tempSub = strcat(tempSub, temp); //add / to entry name
tempSub
points to the t3
array, which only has 2 bytes. Concatenating temp
to it writes outside the array bounds, which causes undefined behavior.
You should calculate the total length of temp_full_path
by adding the lengths of subDir
, t3
, temp
, plus 1 for the null terminator, and allocate that. Since you only need this within the current loop iteration, you can use a variable-length array rather than malloc()
(your code never calls free(temp_full_path)
).
Replace
char *tempSub = t3;
tempSub = strcat(tempSub, temp); //add / to entry name
char *temp_full_path = malloc(sizeof(char) * 2000);
temp_full_path = strcpy(temp_full_path, subDir);
strcat(temp_full_path, tempSub); //gives full path
with
char temp_full_path[strlen(subDir) strlen(t3) strlen(temp) 1];
sprintf(temp_full_path, "%s%s%s", subDir, t3, temp);