Welcome! Log In Create A New Profile

Advanced

SMB recursive directory scan

Posted by DrTwox 
SMB recursive directory scan
March 26, 2009 04:30AM
Hi all.

I have a function to recurse through a directory tree, processing each file found. It works on Linux, Windows and the Wii SD or USB devices... however, if trying to recurse a SMB share, it doesn't work.

e.g. Using the follow directory tree as an example...
directory1/
    sub_directory1/
        file1
        file2
        file3
    sub_directory2/
        file4
        file5
        file6
directory2/
    sub_directory3/
        file7
    sub_directory4/
        file8
...scanning this on the sd:/ or usb:/ device will find all the files, but smb:/ will traverse into directory1, then sub_directory1, find file1, file2 and file3, then not find anything else.

Here's the function:
void recurse(char *path) {
    DIR *dir = opendir(path);
    if (!dir) {
        printf("failed to open directory \"%s\"\n", path);
	return;
    }

    if (chdir(path) != 0) {
	printf("failed to change working directory to \"%s\"\n", path);
	return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if ( (strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0) ) {
            struct stat fileInfo;
            if (stat(entry->d_name, &fileInfo) == 0) {
                if (S_ISDIR(fileInfo.st_mode)) {
                    recurse(entry->d_name);
                    chdir("..");
                } else
                if (S_ISREG(fileInfo.st_mode)) {
                    /* print the file name */
                    char fullPath[ 1024 ] = {'\0'};
                    getcwd(fullPath, sizeof(fullPath));
                    strcat(fullPath, entry->d_name);
                    printf("found:%s\n", fullPath);
                }
            }
        }
    }
    closedir(dir);
}
Any ideas? I seem to remember seeing a tinysmb recurse example someplace, but I can't find it now.
Re: SMB recursive directory scan
March 26, 2009 06:16AM
This is a tinysmb bug to do with the file attributes. I've just rewritten the code in tinysmb that handles the file info, this might solve your problem.
Re: SMB recursive directory scan
March 26, 2009 07:13AM
Awesome, thank you! Available in libogc SVN in the next few days?
Re: SMB recursive directory scan
March 26, 2009 10:24PM
Yes, I'll put it on SVN soon. Please test it. =)
Re: SMB recursive directory scan
March 27, 2009 10:52AM
Now it finds one file and stops :P
Here's the test app I'm using: (Forgive how messy it is - it is just a test after all!)
#include < stdio.h  >
#include < stdlib.h >
#include < unistd.h >
#include < string.h >
#include < gccore.h >
#include < network.h >
#include < errno.h >
#include < wiiuse/wpad.h >
#include < fat.h >
#include < smb.h >
#include < sys/stat.h >
#include < dirent.h >

static void *xfb = NULL;
static GXRModeObj *rmode = NULL;

void recurse(char *path) {
    DIR *dir = opendir(path);
    if (!dir) {
        printf("failed to open directory \"%s\"\n", path);
        return;
    }

    if (chdir(path) != 0) {
        printf("failed to change working directory to \"%s\"\n", path);
        return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if ( (strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0) ) {
            struct stat fileInfo;
            if (stat(entry->d_name, &fileInfo) == 0) {
                if (S_ISDIR(fileInfo.st_mode)) {
                    recurse(entry->d_name);
                    chdir("..");
                } else
                if (S_ISREG(fileInfo.st_mode)) {
                    /* print the file name */
                    char fullPath[ 1024 ] = {'\0'};
                    getcwd(fullPath, sizeof(fullPath));
                    strcat(fullPath, entry->d_name);
                    printf("found:%s\n", fullPath);
                }
            }
        }
    }
    closedir(dir);
}

int main(int argc, char **argv) {
    VIDEO_Init();
    WPAD_Init();
    rmode = VIDEO_GetPreferredMode(NULL);
    xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
    console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
    VIDEO_Configure(rmode);
    VIDEO_SetNextFramebuffer(xfb);
    VIDEO_SetBlack(FALSE);
    VIDEO_Flush();
    VIDEO_WaitVSync();
    if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();

    /* Init the fat file system */
    fatInitDefault();

    /* Init smb file system */
    printf("  init network...");
    while (net_init() == -EAGAIN);
    char myIP[16];
    if (if_config(myIP, NULL, NULL, true) < 0) {
        printf("failed to init network interface\n");
        exit(EXIT_FAILURE);
    }
    printf("%s\n", myIP);

    if (smbInit("guest", "guest", "Music", "192.168.0.1") != true) {
        printf("  failed to connect to smb share\n");
        exit(EXIT_FAILURE);
    }
    printf("  connected to smb share\n");

    recurse("smb:/");

    printf("\n  DONE\n");

    while(1) {
        WPAD_ScanPads();
        u32 pressed = WPAD_ButtonsDown(0);
        if ( pressed & WPAD_BUTTON_HOME ) exit(0);
        VIDEO_WaitVSync();
    }

    return 0;
}
Re: SMB recursive directory scan
April 04, 2009 05:20AM
I don't have the time to look at this more right now, but what I've found is that it has no problems entering a directory and listing the contents, it just has problems backing out and continuing on with the parent directory's listing. If you want to implement some sort of recursive listing like this, you'll have to find your own workaround for the problem (eg: storing a list of directories to recurse, but not actually entering them to parse until you're finished parsing the parent). Or, if you're feeling adventurous you can look at the SMB and SMB devoptab sources and try to fix the problem.
Re: SMB recursive directory scan
April 04, 2009 06:01AM
Thanks for having a look at it. I've had a bit of a mess around with smb_devoptab.c, I'll see what I can do... unfortunately that's probably very little :P
Sorry, only registered users may post in this forum.

Click here to login