1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "android/avd/scanner.h"
15
16 #include "android/avd/util.h"
17 #include "android/emulation/bufprint_config_dirs.h"
18 #include "android/utils/bufprint.h"
19 #include "android/utils/debug.h"
20 #include "android/utils/dirscanner.h"
21 #include "android/utils/path.h"
22 #include "android/utils/system.h"
23
24 #include <string.h>
25
26 #define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
27
28 struct AvdScanner {
29 DirScanner* scanner;
30 char temp[PATH_MAX];
31 char name[PATH_MAX];
32 };
33
avdScanner_new(const char * sdk_home)34 AvdScanner* avdScanner_new(const char* sdk_home) {
35 AvdScanner* s;
36
37 ANEW0(s);
38
39 char* p = s->temp;
40 char* end = p + sizeof(s->temp);
41
42 if (!sdk_home) {
43 p = bufprint_avd_home_path(p, end);
44 } else {
45 p = bufprint(p, end, "%s" PATH_SEP ANDROID_AVD_DIR, sdk_home);
46 }
47
48 if (p >= end) {
49 // Path is too long, no search will be performed.
50 D("Path too long: %s\n", s->temp);
51 return s;
52 }
53 if (!path_is_dir(s->temp)) {
54 // Path does not exist, no search will be performed.
55 D("Path is not a directory: %s\n", s->temp);
56 return s;
57 }
58 s->scanner = dirScanner_new(s->temp);
59 return s;
60 }
61
avdScanner_next(AvdScanner * s)62 const char* avdScanner_next(AvdScanner* s) {
63 if (s->scanner) {
64 for (;;) {
65 const char* entry = dirScanner_next(s->scanner);
66 if (!entry) {
67 // End of enumeration.
68 break;
69 }
70 size_t entry_len = strlen(entry);
71 if (entry_len < 4 ||
72 memcmp(entry + entry_len - 4U, ".ini", 4) != 0) {
73 // Can't possibly be a <name>.ini file.
74 continue;
75 }
76
77 // It's a match, get rid of the .ini suffix and return it.
78 entry_len -= 4U;
79 if (entry_len >= sizeof(s->name)) {
80 D("Name too long: %s\n", entry);
81 continue;
82 }
83 memcpy(s->name, entry, entry_len);
84 s->name[entry_len] = '\0';
85 return s->name;
86 }
87 }
88 return NULL;
89 }
90
avdScanner_free(AvdScanner * s)91 void avdScanner_free(AvdScanner* s) {
92 if (s) {
93 if (s->scanner) {
94 dirScanner_free(s->scanner);
95 s->scanner = NULL;
96 }
97 AFREE(s);
98 }
99 }
100