// Copyright 2020 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "android/avd/scanner.h" #include "android/avd/util.h" #include "android/emulation/bufprint_config_dirs.h" #include "android/utils/bufprint.h" #include "android/utils/debug.h" #include "android/utils/dirscanner.h" #include "android/utils/path.h" #include "android/utils/system.h" #include #define D(...) VERBOSE_PRINT(init,__VA_ARGS__) struct AvdScanner { DirScanner* scanner; char temp[PATH_MAX]; char name[PATH_MAX]; }; AvdScanner* avdScanner_new(const char* sdk_home) { AvdScanner* s; ANEW0(s); char* p = s->temp; char* end = p + sizeof(s->temp); if (!sdk_home) { p = bufprint_avd_home_path(p, end); } else { p = bufprint(p, end, "%s" PATH_SEP ANDROID_AVD_DIR, sdk_home); } if (p >= end) { // Path is too long, no search will be performed. D("Path too long: %s\n", s->temp); return s; } if (!path_is_dir(s->temp)) { // Path does not exist, no search will be performed. D("Path is not a directory: %s\n", s->temp); return s; } s->scanner = dirScanner_new(s->temp); return s; } const char* avdScanner_next(AvdScanner* s) { if (s->scanner) { for (;;) { const char* entry = dirScanner_next(s->scanner); if (!entry) { // End of enumeration. break; } size_t entry_len = strlen(entry); if (entry_len < 4 || memcmp(entry + entry_len - 4U, ".ini", 4) != 0) { // Can't possibly be a .ini file. continue; } // It's a match, get rid of the .ini suffix and return it. entry_len -= 4U; if (entry_len >= sizeof(s->name)) { D("Name too long: %s\n", entry); continue; } memcpy(s->name, entry, entry_len); s->name[entry_len] = '\0'; return s->name; } } return NULL; } void avdScanner_free(AvdScanner* s) { if (s) { if (s->scanner) { dirScanner_free(s->scanner); s->scanner = NULL; } AFREE(s); } }