1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <cutils/properties.h> 18 19 #include <sys/cdefs.h> 20 #include <sys/types.h> 21 #include <sys/stat.h> 22 23 #include <dirent.h> 24 #include <unistd.h> 25 #include <fcntl.h> 26 27 #include <climits> 28 #include <cerrno> 29 #include <string> 30 31 // Taken from android::base, which wasn't available on platform versions 32 // earlier than nougat. 33 34 static bool ReadFdToString(int fd, std::string* content) { 35 content->clear(); 36 char buf[BUFSIZ]; 37 ssize_t n; 38 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) { 39 content->append(buf, n); 40 } 41 return (n == 0) ? true : false; 42 } 43 44 static bool ReadFileToString(const std::string& path, std::string* content, 45 bool follow_symlinks) { 46 int flags = O_RDONLY | O_CLOEXEC | (follow_symlinks ? 0 : O_NOFOLLOW); 47 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags)); 48 if (fd == -1) { 49 return false; 50 } 51 bool result = ReadFdToString(fd, content); 52 close(fd); 53 return result; 54 } 55 56 int main(int argc __unused, char *argv[] __unused) { 57 const char sysfs_base[] = "/sys/class/virtio-ports/"; 58 DIR *dir = opendir(sysfs_base); 59 if (dir) { 60 dirent *dp; 61 while ((dp = readdir(dir)) != nullptr) { 62 std::string dirname = dp->d_name; 63 std::string sysfs(sysfs_base + dirname + "/name"); 64 struct stat st; 65 if (stat(sysfs.c_str(), &st)) { 66 continue; 67 } 68 std::string content; 69 if (!ReadFileToString(sysfs, &content, true)) { 70 continue; 71 } 72 if (content.empty()) { 73 continue; 74 } 75 content.erase(content.end() - 1); 76 // Leaves 32-11=22 characters for the port name from QEMU. 77 std::string propname("sys.cf.ser." + content); 78 std::string dev("/dev/" + dirname); 79 property_set(propname.c_str(), dev.c_str()); 80 } 81 } 82 return 0; 83 } 84