Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19348f1c authored by Danny Baumann's avatar Danny Baumann
Browse files

Fix media scanning in case readdir() returns type DT_UNKNOWN.

In that case, a stat() fallback was present in the code. The stat()
call, however, wasn't run on the file in question, but the containing
directory. Consequently, the file was treated as a directory, which
resulted in the scan being aborted due to opendir() failing. Example
logcat output:

D/MediaScanner( 2434): opendir
/system/media/audio/alarms/Alarm_Beep_01.ogg/ failed, errno: 20
E/MediaScanner( 2434): Error processing
'/system/media/audio/alarms/Alarm_Beep_01.ogg/' - skipping
D/MediaScanner( 2434): stat() failed for
/system/media/audio/alarms/Alarm_Beep_01.ogg/: Not a directory
D/MediaScanner( 2434): stat() failed for
/system/media/audio/alarms/Alarm_Beep_01.ogg/: Not a directory
D/MediaScanner( 2434): stat() failed for
/system/media/audio/alarms/Alarm_Beep_01.ogg/: Not a directory
[...]

Fix that issue by amending the file name to the buffer prior to calling
stat().
parent 5885a086
Loading
Loading
Loading
Loading
+26 −28
Original line number Diff line number Diff line
@@ -127,12 +127,21 @@ status_t MediaScanner::doProcessDirectory(

    while ((entry = readdir(dir))) {
        const char* name = entry->d_name;
        int nameLength = strlen(name);

        // ignore "." and ".."
        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
            continue;
        }

        /* also keep space for '/' in case it's a directory */
        if (nameLength + 1 > pathRemaining) {
            // path too long!
            continue;
        }

        strcpy(fileSpot, name);

        int type = entry->d_type;
        if (type == DT_UNKNOWN) {
            // If the type is unknown, stat() the file instead.
@@ -149,17 +158,7 @@ status_t MediaScanner::doProcessDirectory(
                LOGD("stat() failed for %s: %s", path, strerror(errno) );
            }
        }
        if (type == DT_REG || type == DT_DIR) {
            int nameLength = strlen(name);
            bool isDirectory = (type == DT_DIR);

            if (nameLength > pathRemaining || (isDirectory && nameLength + 1 > pathRemaining)) {
                // path too long!
                continue;
            }

            strcpy(fileSpot, name);
            if (isDirectory) {
        if (type == DT_DIR) {
            // ignore directories with a name that starts with '.'
            // for example, the Mac ".Trashes" directory
            if (name[0] == '.') continue;
@@ -172,7 +171,7 @@ status_t MediaScanner::doProcessDirectory(
                LOGE("Error processing '%s' - skipping\n", path);
                continue;
            }
            } else if (fileMatchesExtension(path, extensions)) {
        } else if (type == DT_REG && fileMatchesExtension(path, extensions)) {
            struct stat statbuf;
            stat(path, &statbuf);
            if (statbuf.st_size > 0) {
@@ -181,7 +180,6 @@ status_t MediaScanner::doProcessDirectory(
            if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
        }
    }
    }

    closedir(dir);
    return OK;