You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.7 KiB
100 lines
2.7 KiB
// 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 <string.h>
|
|
|
|
#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 <name>.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);
|
|
}
|
|
}
|