aMule Bug Tracker - aMule
View Issue Details
0000140aMuleMiscpublic2004-09-21 16:172004-09-25 19:38
volpol 
Kry 
normalmajoralways
resolvedfixed 
 
 
0000140: CDirIterator::FindNextFile() always returns wxEmptyString (in aMule-cvs-20040921)
CDirIterator::FindNextFile() doesn't work as intended with reiserfs (always returns wxEmptyString) due to the fact that readdir() always returns DT_UNKNOWN for d_type. please refer to http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=210861 [^] for more info.
No tags attached.
Issue History
2004-09-21 16:17volpolNew Issue
2004-09-21 16:45volpolNote Added: 0000261
2004-09-22 17:18KryNote Added: 0000263
2004-09-22 17:21KryStatusnew => acknowledged
2004-09-22 23:51volpolNote Added: 0000267
2004-09-23 01:10KryNote Added: 0000268
2004-09-23 01:10KryNote Edited: 0000268
2004-09-23 01:14KryNote Edited: 0000268
2004-09-23 01:18volpolNote Added: 0000269
2004-09-23 01:27KryNote Added: 0000270
2004-09-23 01:28KryNote Added: 0000271
2004-09-23 01:29KryNote Deleted: 0000271
2004-09-23 01:31KryNote Edited: 0000270
2004-09-23 23:55volpolNote Added: 0000274
2004-09-25 19:38KryStatusacknowledged => resolved
2004-09-25 19:38KryResolutionopen => fixed
2004-09-25 19:38KryAssigned To => Kry
2004-09-25 19:38KryNote Added: 0000277

Notes
(0000261)
volpol   
2004-09-21 16:45   
not sure if it's useful but here's the version of FindNextFile i am using currently.
wxString CDirIterator::FindNextFile() {
        struct dirent *dp;
        dp = readdir(DirPtr);
        bool found = false;
        struct stat* buf=(struct stat*)malloc(sizeof(struct stat));
        wxString FoundName;
        wxString tname;
        while (dp!=NULL && !found) {
                tname=DirStr+char2unicode(dp->d_name);
                stat (unicode2char(tname),buf);
                if (S_ISREG(buf->st_mode)){ if (type == CDirIterator::File) found = true; else dp = readdir(DirPtr);} else
                if (S_ISDIR(buf->st_mode)){ if (type == CDirIterator::Dir) found = true; else dp = readdir(DirPtr);} else
                                // unix socket, block device, etc
                        if ((type == CDirIterator::Any)) // return anything.
                                found = true;
                                else dp = readdir(DirPtr);

                if (found) {
                        FoundName = char2unicode(dp->d_name);
                        if (
                                (!FileMask.IsEmpty() && !FoundName.Matches(FileMask))
                                || FoundName.IsSameAs(wxT(".")) || FoundName.IsSameAs(wxT(".."))) {
                                found = false;
                                dp = readdir(DirPtr);
                        }
                }
        }
        free(buf);
        if (dp!=NULL) {
                return DirStr + FoundName;
        } else {
                return wxEmptyString;
        }
}
(0000263)
Kry   
2004-09-22 17:18   
Many thanks, With small changes, it will be on CVS ASAP. Sorry for the bug :)
(0000267)
volpol   
2004-09-22 23:51   
it's ok. keep up the good work! =)
(0000268)
Kry   
2004-09-23 01:10   
(edited on: 2004-09-23 01:14)
This is my final version:

wxString CDirIterator::FindNextFile() {
    struct dirent *dp;
    dp = readdir(DirPtr);

    bool found = false;
    
    wxString FoundName;
    
    struct stat* buf=(struct stat*)malloc(sizeof(struct stat));
    
    while (dp!=NULL && !found) {
        if ((type == CDirIterator::Any)) {
            // return anything.
            found = true;
        } else {
            switch (dp->d_type) {
                case DT_DIR:
                    if (type == CDirIterator::Dir) {
                        found = true;
                    } else {
                        dp = readdir(DirPtr);
                    }
                    break;
                case DT_REG:
                    if (type == CDirIterator::File) {
                        found = true;
                    } else {
                        dp = readdir(DirPtr);
                    }
                    break;
                default:
                    // Fallback to stat
                    stat(unicode2char(tname),buf);
                    if (S_ISREG(buf->st_mode)) {
                        if (type == CDirIterator::File) {
                            found = true;
                        } else {
                            dp = readdir(DirPtr);
                        }
                    } else {
                        if (S_ISDIR(buf->st_mode)) {
                            if (type == CDirIterator::Dir) {
                                found = true;
                            } else {
                                dp = readdir(DirPtr);
                            }
                        } else {
                            // unix socket, block device, etc
                            dp = readdir(DirPtr);
                        }
                    }
                    break;
            }
        }
        if (found) {
            FoundName = char2unicode(dp->d_name);
            if (
                (!FileMask.IsEmpty() && !FoundName.Matches(FileMask))
                || FoundName.IsSameAs(wxT(".")) || FoundName.IsSameAs(wxT(".."))) {
                found = false;
                dp = readdir(DirPtr);
            }
        }
    }
            
    free(buf);
    
    if (dp!=NULL) {
        return DirStr + FoundName;
    } else {
        return wxEmptyString;
    }
}

Is much longer than yours, but I like it more ;) It avoids stat while we can :)

edited on: 09-23-04 01:10

edited on: 09-23-04 01:14
(0000269)
volpol   
2004-09-23 01:18   
that's understandable since i only have to make it work for me while you have to make it portable =p where is tname defined in your version by the way? and also one can eliminate a few if's by using something like (S_REG(...) && (type == CDirIterator::File)) i realized it a bit later...back then i was too eager to make aMule finally find my temporary and shared files =p
(0000270)
Kry   
2004-09-23 01:27   
(edited on: 2004-09-23 01:31)
lol, ok, I won't poste code again BEFORe compiling it ;)

stat(unicode2char(DirStr + dp->d_name),buf);

Want this to be your first patch to aMule? (one of many!) go on and paste your optimisations :)

edited on: 09-23-04 01:31
(0000274)
volpol   
2004-09-23 23:55   
hmmm...one can concatenate wsString and char[] like that...i didn't know. lol, or maybe that's how it's done in c++. i would probably give strcat() a chance =p anyway further optimization seems to be unnecessary. waiting for the fix to appear in CVS.
(0000277)
Kry   
2004-09-25 19:38   
Yo, on CVS