MediaScanResult MediaScanner::doProcessDirectory(
        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) {
#ifndef ANDROID_DEFAULT_CODE
    LOGV("doProcessDirectory %s extensions: %s\n", path, extensions);
#endif   

    // place to copy file or directory name
    char* fileSpot = path + strlen(path);
    struct dirent* entry;

    if (shouldSkipDirectory(path)) {
      LOGD("Skipping: %s", path);
      return MEDIA_SCAN_RESULT_OK;
    }

    // Treat all files as non-media in directories that contain a  ".nomedia" file
    if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
        strcpy(fileSpot, ".nomedia");
        if (access(path, F_OK) == 0) {
            LOGV("found .nomedia, setting noMedia flag\n");
            noMedia = true;
        }

        // restore path
        fileSpot[0] = 0;
    }

    DIR* dir = opendir(path);
    if (!dir) {
        LOGW("Error opening directory '%s', skipping: %s.", path, strerror(errno));
        return MEDIA_SCAN_RESULT_SKIPPED;
    }
#ifndef ANDROID_DEFAULT_CODE
    //--start--find the best file to set default ringtone.
    static bool isSetRingtone = false;
    static bool isSetNotification = false;
    static bool isSetAlarm = false;
    bool needFindFile = false;
    if (isSetRingtone == false) {
        if (strcmp(path, "/system/media/audio/ringtones/") == 0) {
            needFindFile = true;
            isSetRingtone = true;
        }
    }
    if (isSetNotification == false) {
        if (strcmp(path, "/system/media/audio/notifications/") == 0) {
            needFindFile = true;
            isSetNotification = true;
        }
    }
    if (isSetAlarm == false) {
            if (strcmp(path, "/system/media/audio/alarms/") == 0) {
                needFindFile = true;
                isSetAlarm = true;
            }
        }
    if (needFindFile) {
        char* findFile = 0;
        while ((entry = readdir(dir))) {
            const char* name = entry->d_name;
            // ignore "." and ".."
            if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
                continue;
            }
            int type = entry->d_type;
            if (type == DT_UNKNOWN) {
                // If the type is unknown, stat() the file instead.
                // This is sometimes necessary when accessing NFS mounted filesystems, but
                // could be needed in other cases well.
                struct stat statbuf;
                if (stat(path, &statbuf) == 0) {
                    if (S_ISREG(statbuf.st_mode)) {
                        type = DT_REG;
                    } else if (S_ISDIR(statbuf.st_mode)) {
                        type = DT_DIR;
                    }
                } else {
                    LOGD("stat() failed for %s: %s", path, strerror(errno) );
                }
            }
            if (type == DT_REG) {
                int nameLength = strlen(name);
                if (nameLength > pathRemaining) {
                    // path too long!
                    continue;
                }
                int pathLength = strlen(path);
                strcpy(fileSpot, name);
                //if (fileMatchesExtension(path, extensions)) {
                    if (findFile == 0) {
                        findFile = new char[pathLength + pathRemaining];
                        strcpy(findFile, path);
                    } else {
                        if (strcmp(path, findFile) < 0) {
                            strcpy(findFile, path);
                        }
                    }
               // }
            }
        }
        if (findFile != 0) {
            struct stat statbuf;
            stat(findFile, &statbuf);
            if (statbuf.st_size > 0) {
                LOGD("find the default audio file = %s", findFile);
               // client.scanFile(findFile, statbuf.st_mtime, statbuf.st_size);
               //need audio owner check
               client.scanFile(findFile, statbuf.st_mtime, statbuf.st_size,false,false);
            }
            delete findFile;
            findFile = 0;
           // if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
        } else {
            LOGD("Can not get the best file for ringtone");
        }
        closedir(dir);
        //restore the path
        fileSpot[0] = 0;
        //reopen the dir for android's default deal.
        dir = opendir(path);
        if (!dir) {
            LOGD("opendir %s failed, errno: %d", path, errno);
            return MEDIA_SCAN_RESULT_ERROR;
        }
    }
    //--end--find the best file to set default ringtone.
#endif


    MediaScanResult result = MEDIA_SCAN_RESULT_OK;
    while ((entry = readdir(dir))) {
        if (doProcessDirectoryEntry(path, pathRemaining, client, noMedia, entry, fileSpot)
                == MEDIA_SCAN_RESULT_ERROR) {
            result = MEDIA_SCAN_RESULT_ERROR;
            break;
        }
    }
    closedir(dir);
    return result;
}
Beispiel #2
0
MediaScanResult MediaScanner::doProcessDirectoryEntry(
        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
        struct dirent* entry, char* fileSpot) {
    struct stat statbuf;
    const char* name = entry->d_name;
#ifndef ANDROID_DEFAULT_CODE
    ALOGV("doProcessDirectoryEntry: %s \n", path);
#endif 
    // ignore "." and ".."
    if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }

    int nameLength = strlen(name);
    if (nameLength + 1 > pathRemaining) {
        // path too long!
        return MEDIA_SCAN_RESULT_SKIPPED;
    }
    strcpy(fileSpot, name);

    int type = entry->d_type;
    if (type == DT_UNKNOWN) {
        // If the type is unknown, stat() the file instead.
        // This is sometimes necessary when accessing NFS mounted filesystems, but
        // could be needed in other cases well.
        if (stat(path, &statbuf) == 0) {
            if (S_ISREG(statbuf.st_mode)) {
                type = DT_REG;
            } else if (S_ISDIR(statbuf.st_mode)) {
                type = DT_DIR;
            }
        } else {
            ALOGD("stat() failed for %s: %s", path, strerror(errno) );
        }
    }
    if (type == DT_DIR) {
        bool childNoMedia = noMedia;
        // set noMedia flag on directories with a name that starts with '.'
        // for example, the Mac ".Trashes" directory
        if (name[0] == '.')
            childNoMedia = true;

        // report the directory to the client
        if (stat(path, &statbuf) == 0) {
            status_t status = client.scanFile(path, statbuf.st_mtime, 0,
                    true /*isDirectory*/, childNoMedia);
            if (status) {
                return MEDIA_SCAN_RESULT_ERROR;
            }
        }

        // and now process its contents
        strcat(fileSpot, "/");
        MediaScanResult result = doProcessDirectory(path, pathRemaining - nameLength - 1,
                client, childNoMedia);
        if (result == MEDIA_SCAN_RESULT_ERROR) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    } else if (type == DT_REG) {
        stat(path, &statbuf);
        status_t status = client.scanFile(path, statbuf.st_mtime, statbuf.st_size,
                false /*isDirectory*/, noMedia);
        if (status) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    }

    return MEDIA_SCAN_RESULT_OK;
}
Beispiel #3
0
status_t MediaScanner::doProcessDirectory(
        char *path, int pathRemaining, const char *extensions,
        MediaScannerClient &client, ExceptionCheck exceptionCheck,
        void *exceptionEnv) {
    // place to copy file or directory name
    char* fileSpot = path + strlen(path);
    struct dirent* entry;
    char* tempPathBuffer = NULL;
    char* pathBuffer = NULL;
    DIR* dir = NULL;
    int pathLength = strlen(path);
    if (pathLength >= PATH_MAX) {
        goto failure;
    }
    pathBuffer = (char *)malloc(PATH_MAX + 1);
    tempPathBuffer = (char *)malloc(PATH_MAX + 1);
    if (!pathBuffer || !tempPathBuffer) {
        goto failure;
    }

    strcpy(pathBuffer, path);
    // ignore directories that contain a  ".nomedia" file
    if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
        strcpy(fileSpot, ".nomedia");
        if (access(path, F_OK) == 0) {
            LOGD("found .nomedia, skipping directory\n");
            fileSpot[0] = 0;
            client.addNoMediaFolder(path);
            goto success;
        }
        // restore path
        fileSpot[0] = 0;
    }

    dir = opendir(path);
    if (!dir) {
        LOGD("opendir %s failed, errno: %d", path, errno);
        goto failure;
    }

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

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

        int type = entry->d_type;
        if (type == DT_UNKNOWN) {
            // If the type is unknown, stat() the file instead.
            // This is sometimes necessary when accessing NFS mounted filesystems, but
            // could be needed in other cases well.
            struct stat statbuf;
            int tempPathLength = strlen(pathBuffer) + strlen(name);
            if (tempPathLength >= PATH_MAX) {
                goto failure;
            }

            strcpy(tempPathBuffer, pathBuffer);
            strcat(tempPathBuffer, name);
            if (stat(tempPathBuffer, &statbuf) == 0) {
                if (S_ISREG(statbuf.st_mode)) {
                    type = DT_REG;
                } else if (S_ISDIR(statbuf.st_mode)) {
                    type = DT_DIR;
                }
            } else {
                LOGD("stat() failed for %s %s: %s", path, name, 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) {
                // ignore directories with a name that starts with '.'
                // for example, the Mac ".Trashes" directory
                if (name[0] == '.') continue;

                strcat(fileSpot, "/");
                int err = doProcessDirectory(path, pathRemaining - nameLength - 1, extensions, client, exceptionCheck, exceptionEnv);
                if (err) {
                    // pass exceptions up - ignore other errors
                    if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
                    LOGE("Error processing '%s' - skipping\n", path);
                    continue;
                }
            } else if (fileMatchesExtension(path, extensions)) {
                struct stat statbuf;
                stat(path, &statbuf);
                if (statbuf.st_size > 0) {
                    client.scanFile(path, statbuf.st_mtime, statbuf.st_size);
                }
                if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
            }
        }
    }
    closedir(dir);
success:
    free(pathBuffer);
    free(tempPathBuffer);
    return OK;
failure:
    free(pathBuffer);
    free(tempPathBuffer);
    closedir(dir);
    return -1;
}