1 /*
2  * Copyright (C) 2008 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 <stdio.h>
18 #include <stdlib.h>
19 #include <sys/stat.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <inttypes.h>
24 
25 #include "private/android_filesystem_config.h"
26 #include "private/fs_config.h"
27 
28 // This program takes a list of files and directories (indicated by a
29 // trailing slash) on the stdin, and prints to stdout each input
30 // filename along with its desired uid, gid, and mode (in octal).
31 // The leading slash should be stripped from the input.
32 //
33 // After the first 4 columns, optional key=value pairs are emitted
34 // for each file.  Currently, the following keys are supported:
35 //
36 //   -C: capabilities=[hex capabilities value]
37 //
38 // Example input:
39 //
40 //      system/etc/dbus.conf
41 //      data/app/
42 //
43 // Output:
44 //
45 //      system/etc/dbus.conf 1002 1002 440
46 //      data/app 1000 1000 771
47 //
48 // Note that the output will omit the trailing slash from
49 // directories.
50 
usage()51 static void usage() {
52   fprintf(stderr, "Usage: fs_config [-D product_out_path] [-R root] [-C]\n");
53 }
54 
main(int argc,char ** argv)55 int main(int argc, char** argv) {
56   char buffer[1024];
57   const char* product_out_path = NULL;
58   char* root_path = NULL;
59   int print_capabilities = 0;
60   int opt;
61   while((opt = getopt(argc, argv, "CR:D:")) != -1) {
62     switch(opt) {
63     case 'C':
64       print_capabilities = 1;
65       break;
66     case 'R':
67       root_path = optarg;
68       break;
69     case 'D':
70       product_out_path = optarg;
71       break;
72     default:
73       usage();
74       exit(EXIT_FAILURE);
75     }
76   }
77 
78   if (root_path != NULL) {
79     size_t root_len = strlen(root_path);
80     /* Trim any trailing slashes from the root path. */
81     while (root_len && root_path[--root_len] == '/') {
82       root_path[root_len] = '\0';
83     }
84   }
85 
86   while (fgets(buffer, 1023, stdin) != NULL) {
87     int is_dir = 0;
88     int i;
89     for (i = 0; i < 1024 && buffer[i]; ++i) {
90       switch (buffer[i]) {
91         case '\n':
92           buffer[i-is_dir] = '\0';
93           if (i == 0) {
94             is_dir = 1; // empty line is considered as root directory
95           }
96           i = 1025;
97           break;
98         case '/':
99           is_dir = 1;
100           break;
101         default:
102           is_dir = 0;
103           break;
104       }
105     }
106 
107     unsigned uid = 0, gid = 0, mode = 0;
108     uint64_t capabilities;
109     fs_config(buffer, is_dir, product_out_path, &uid, &gid, &mode, &capabilities);
110     if (root_path != NULL && strcmp(buffer, root_path) == 0) {
111       /* The root of the filesystem needs to be an empty string. */
112       strcpy(buffer, "");
113     }
114     printf("%s %d %d %o", buffer, uid, gid, mode);
115 
116     if (print_capabilities) {
117       printf(" capabilities=0x%" PRIx64, capabilities);
118     }
119 
120     printf("\n");
121   }
122   return 0;
123 }
124