MediaScanResult MediaScanner::processDirectory( const char *path, MediaScannerClient &client) { #ifndef ANDROID_DEFAULT_CODE ALOGI("processDirectory: %s \n", path); #endif int pathLength = strlen(path); if (pathLength >= PATH_MAX) { return MEDIA_SCAN_RESULT_SKIPPED; } char* pathBuffer = (char *)malloc(PATH_MAX + 1); if (!pathBuffer) { return MEDIA_SCAN_RESULT_ERROR; } int pathRemaining = PATH_MAX - pathLength; strcpy(pathBuffer, path); if (pathLength > 0 && pathBuffer[pathLength - 1] != '/') { pathBuffer[pathLength] = '/'; pathBuffer[pathLength + 1] = 0; --pathRemaining; } client.setLocale(locale()); MediaScanResult result = doProcessDirectory(pathBuffer, pathRemaining, client, false); free(pathBuffer); return result; }
status_t MediaScanner::processDirectory( const char *path, const char *extensions, MediaScannerClient &client, ExceptionCheck exceptionCheck, void *exceptionEnv) { int pathLength = strlen(path); if (pathLength >= PATH_MAX) { return UNKNOWN_ERROR; } char* pathBuffer = (char *)malloc(PATH_MAX + 1); if (!pathBuffer) { return UNKNOWN_ERROR; } int pathRemaining = PATH_MAX - pathLength; strcpy(pathBuffer, path); if (pathLength > 0 && pathBuffer[pathLength - 1] != '/') { pathBuffer[pathLength] = '/'; pathBuffer[pathLength + 1] = 0; --pathRemaining; } client.setLocale(locale()); status_t result = doProcessDirectory( pathBuffer, pathRemaining, extensions, client, exceptionCheck, exceptionEnv); free(pathBuffer); return result; }
MediaScanResult MediaScanner::processDirectory( const char *path, MediaScannerClient &client) { #ifdef MTK_AOSP_ENHANCEMENT ALOGI("processDirectory: %s \n", path); #endif int pathLength = strlen(path); if (pathLength >= PATH_MAX) { return MEDIA_SCAN_RESULT_SKIPPED; } char* pathBuffer = (char *)malloc(PATH_MAX + 1); if (!pathBuffer) { return MEDIA_SCAN_RESULT_ERROR; } int pathRemaining = PATH_MAX - pathLength; strcpy(pathBuffer, path); if (pathLength > 0 && pathBuffer[pathLength - 1] != '/') { pathBuffer[pathLength] = '/'; pathBuffer[pathLength + 1] = 0; --pathRemaining; } client.setLocale(locale()); /// M: add for the new feature about the new thread pool on JB9.MP/KK/KK.AOSP branch bool flag = false; for (int i = pathLength - 1; i >= 1; i--) { if ((pathBuffer[i] == '.') && (pathBuffer[i - 1] == '/')) { ALOGW("Include nomeida folder."); flag = true; } } MediaScanResult result = doProcessDirectory(pathBuffer, pathRemaining, client, flag); /// @} free(pathBuffer); return result; }
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; }
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; }