Search code examples
cglob

Glob with a user supplied directory?


I am writing a program that should search through a directory that the user supplies in order to find all files in said directory that were accessed, modified, or changed within a day of a given time. I am having two definite problem and perhaps another one.

The first problem is that I can only get the program to do shallow searches, it won't look through any subdirectories. I am sure it has to do with what I concatenate to the directory buffer ( right now it is .). The second problem is that it is not searching every file, though it does look at most of them - I think this goes back to problem one though. The third "problem" is that when I check the access time of each file, it seems as though they are all the same (though I don't have this problem with changed/modified time). I am running on Ubuntu through VM, if that might be affecting the access times.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <glob.h>

/* Function that checks if specified file was accessed, modified, or
changed within a day of the specified time.                 */
void checkFile(long long time, char * fileName) {
struct stat *s;
time_t accessTime;
time_t modTime;
time_t changeTime;
s = malloc(sizeof(struct stat));
if(stat(fileName,s) == 0) {
    accessTime = s->st_atime;
    modTime = s->st_mtime;      
    changeTime = s->st_ctime;
    if((time - accessTime) <= 86400 && (time - accessTime) >= -86400)
        printf("%s\n",fileName);
    else if((time - modTime) <= 86400 && (time - modTime) >= -86400)
        printf("%s\n",fileName);
    else if((time - changeTime) <= 86400 && (time - changeTime) >= -86400)
        printf("%s\n",fileName);
}
free(s);
}

void searchDirectory(long long time, glob_t globbuf) {
if(globbuf.gl_pathc == 0)
    printf("there were no matching files");
else {
    int i;
    for(i = 0; i < globbuf.gl_pathc; i++)
        checkFile(time,globbuf.gl_pathv[i]);
}
}

int main(int argc, char** argv) {
    long long time = atol(argv[1]);
    char * buf = argv[2];
    strcat(buf,"*.*");
    glob_t globbuf;
    glob(buf, 0, NULL, &globbuf);
    searchDirectory(time,globbuf);
    globfree(&globbuf);
    return 0;
}

Thanks for your time!


Solution

  • You should not

    cat(buf, "*.*");
    

    ...since 'buf' is a pointer to a string provided by the os - you don't know if that buffer is large enough to hold the extra text you are adding. You could allocate a large buffer, copy the contents of argv[2] into it and then append "*.*", but to be really safe you should determine the length of argv[2] and ensure your buffer is large enough.

    You can use the st_mode member of the struct stat structure to determine if the file is a directory (check if it equals S_IFDIR). If it is, you could make it the current directory and as jonsca suggested, call your searchDirectory function again. But when using recursion you usually want to ensure you have a limit on the depth of recursion, or you can overflow the stack. This is a kind of 'depth first search'. The solution I prefer is to do a 'breadth first search' using a queue: basically push your first glob onto the start of a list, then repeatedly take the first item off that list and search it, adding new directories to the end of the list as you go, until the list is empty.

    When evaluating programs like this, teachers love to award extra points for those that don't blow their stack too easily :)

    P.S. I'm guessing the access time issue is a VM/filesystem/etc incompatibility and not your fault.