|
-
February 3rd, 2011, 04:08 PM
#1
Strange segfault on linux only
I'm receiving a very strange segfault on line 94 in the traverse method below, the first time it runs. This is very strange and I have no idea what is causing it. I've debugged the program on XCode and see no problems, and I'm starting to think that it's a gcc bug.
Whatever it is is even causing Valgrind to segfault. Valgrind picks up several jumps based on uninitialized values within strcat. Is this a gcc bug, or does someone see a problem with my code?
Code:
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
char * findTab(char * str){
bool quote = false;
for (;*str;++str){
switch(*str){
case '\\':
++str;
if (!(*str)) return NULL;
break;
case '\"':
quote = !quote;
break;
case '\t':
if (!quote) return str;
break;
}
}
return NULL;
}
static bool tryfile(char * filename){
printf("Working on %s... ", filename);
char * ext = filename + strlen(filename) - 4;
if (strcmp(ext, ".php")){
printf("skipping\n");
return false; //not a PHP file
}
struct stat stbuf;
stat(filename, &stbuf);
FILE * fp = fopen(filename, "r");
if (!fp){
printf("failed to open\n");
return false;
}
size_t characters = stbuf.st_size * 2;
char * contents = (char*)malloc(characters * sizeof(char));
size_t len = fread(contents, 1, stbuf.st_size, fp);
fclose(fp);
if (len != stbuf.st_size){
printf("load failed\n");
free(contents);
return false;
}
contents[len] = '\0';
char * tab = findTab(contents);
int tabs = 0;
while (tab){
char * buffer = (char*)malloc(characters * sizeof(char));
memcpy(buffer, contents, ((long)tab - (long)contents) * sizeof(char));
strcat(buffer, " ");
strcat(buffer, tab + 1);
strcpy(contents, buffer);
free(buffer);
if (strlen(contents) > characters - 10){
characters *= 2;
contents = (char*)realloc(contents, characters);
}
++tabs;
tab = findTab(contents);
}
fp = fopen(filename, "w");
if (!fp){
printf("failed to open for output\n");
free(contents);
return false;
}
size_t bytes = strlen(contents) * sizeof(char);
size_t check = fwrite(contents, 1, bytes, fp);
fclose(fp);
free(contents);
if (bytes != check){
printf("failed to write new file\n", tabs);
return false;
}
printf("done, replaced %d tabs\n", tabs);
return true;
}
static bool traverse(char * name, bool recurse){
char buffer[256];
strcpy(buffer, name);
strcat(buffer, "/");
DIR * dir = opendir(name);
if (dir){
struct dirent * dp;
if (!(dp = readdir(dir))) return false; //.
if (!(dp = readdir(dir))) return false; //..
while (dp = readdir(dir)){
if (dp -> d_name[0] != '.'){ //ignore hidden files and folders
strcpy(buffer, name);
strcat(buffer, "/");
strcat(buffer, dp -> d_name);
if ((!recurse) || (!traverse(buffer, recurse))){
tryfile(buffer);
}
}
}
return true;
}
//not a directory
return false;
}
int main(int argc, char ** argv){
printf("Checking parameter count\n");
//check that the dir param is there
if ((argc != 2) && (argc != 3)){
printf("You have to give this program a directory as an argument\n");
return 0;
}
printf("Checking for recursive param\n");
bool recurse = false;
if (argc == 3){
printf("Checking recursive param is correct\n");
if (strcmp(argv[2], "-r")){
printf("The correct parameters are %s file/dir [-r]\n", argv[0]);
return 0;
}
recurse = true;
}
printf("Starting %s\n", argv[1]);
if (!traverse(argv[1], recurse)){
if (!tryfile(argv[1])){
printf("%s doesnt appear to exist or is not a directory\n", argv[1]);
return 0;
}
}
return 0;
}
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|