1 /* 2 * Copyright (C) 2014 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 <inttypes.h> 18 #include <stdio.h> 19 #include <string.h> 20 #include <errno.h> 21 #include <limits.h> 22 #include <stdlib.h> 23 24 #include <private/android_filesystem_config.h> 25 #include <private/canned_fs_config.h> 26 27 typedef struct { 28 const char* path; 29 unsigned uid; 30 unsigned gid; 31 unsigned mode; 32 uint64_t capabilities; 33 } Path; 34 35 static Path* canned_data = NULL; 36 static int canned_alloc = 0; 37 static int canned_used = 0; 38 39 static int path_compare(const void* a, const void* b) { 40 return strcmp(((Path*)a)->path, ((Path*)b)->path); 41 } 42 43 int load_canned_fs_config(const char* fn) { 44 FILE* f = fopen(fn, "r"); 45 if (f == NULL) { 46 fprintf(stderr, "failed to open %s: %s\n", fn, strerror(errno)); 47 return -1; 48 } 49 50 char line[PATH_MAX + 200]; 51 while (fgets(line, sizeof(line), f)) { 52 while (canned_used >= canned_alloc) { 53 canned_alloc = (canned_alloc+1) * 2; 54 canned_data = (Path*) realloc(canned_data, canned_alloc * sizeof(Path)); 55 } 56 Path* p = canned_data + canned_used; 57 p->path = strdup(strtok(line, " ")); 58 p->uid = atoi(strtok(NULL, " ")); 59 p->gid = atoi(strtok(NULL, " ")); 60 p->mode = strtol(strtok(NULL, " "), NULL, 8); // mode is in octal 61 p->capabilities = 0; 62 63 char* token = NULL; 64 do { 65 token = strtok(NULL, " "); 66 if (token && strncmp(token, "capabilities=", 13) == 0) { 67 p->capabilities = strtoll(token+13, NULL, 0); 68 break; 69 } 70 } while (token); 71 72 canned_used++; 73 } 74 75 fclose(f); 76 77 qsort(canned_data, canned_used, sizeof(Path), path_compare); 78 printf("loaded %d fs_config entries\n", canned_used); 79 80 return 0; 81 } 82 83 static const int kDebugCannedFsConfig = 0; 84 85 void canned_fs_config(const char* path, int dir, const char* target_out_path, 86 unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities) { 87 Path key; 88 key.path = path; 89 if (path[0] == '/') 90 key.path++; // canned paths lack the leading '/' 91 Path* p = (Path*) bsearch(&key, canned_data, canned_used, sizeof(Path), path_compare); 92 if (p == NULL) { 93 fprintf(stderr, "failed to find [%s] in canned fs_config\n", path); 94 exit(1); 95 } 96 *uid = p->uid; 97 *gid = p->gid; 98 *mode = p->mode; 99 *capabilities = p->capabilities; 100 101 if (kDebugCannedFsConfig) { 102 // for debugging, run the built-in fs_config and compare the results. 103 104 unsigned c_uid, c_gid, c_mode; 105 uint64_t c_capabilities; 106 fs_config(path, dir, target_out_path, &c_uid, &c_gid, &c_mode, &c_capabilities); 107 108 if (c_uid != *uid) printf("%s uid %d %d\n", path, *uid, c_uid); 109 if (c_gid != *gid) printf("%s gid %d %d\n", path, *gid, c_gid); 110 if (c_mode != *mode) printf("%s mode 0%o 0%o\n", path, *mode, c_mode); 111 if (c_capabilities != *capabilities) 112 printf("%s capabilities %" PRIx64 " %" PRIx64 "\n", 113 path, 114 *capabilities, 115 c_capabilities); 116 } 117 } 118