OSDN Git Service

Add a script to run Android-x86 in QEMU
[android-x86/bootable-newinstaller.git] / editdisklbl / editdisklbl.c
1 /* tools/editdisklbl/editdisklbl.c
2  *
3  * Copyright 2008, The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #define __USE_LARGEFILE64
19 #define __USE_FILE_OFFSET64
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28
29 #include "diskconfig/diskconfig.h"
30
31 /* give us some room */
32 #define EXTRA_LBAS      100
33
34 static struct pf_map {
35     struct part_info *pinfo;
36     const char *filename;
37 } part_file_map[MAX_NUM_PARTS] = { {0, 0} };
38
39 static int
40 usage(void)
41 {
42     fprintf(stderr,
43             "\nusage: editdisklbl <options> part1=file1 [part2=file2,...]\n"
44             "Where options can be one of:\n"
45             "\t\t-l <layout conf>  -- The image layout config file.\n"
46             "\t\t-i <image file>   -- The image file to edit.\n"
47             "\t\t-t                -- Test mode (optional)\n"
48             "\t\t-v                -- Be verbose\n"
49             "\t\t-h                -- This message (optional)\n"
50             );
51     return 1;
52 }
53
54 static int
55 parse_args(int argc, char *argv[], struct disk_info **dinfo, int *test,
56            int *verbose)
57 {
58     char *layout_conf = NULL;
59     char *img_file = NULL;
60     struct stat filestat;
61     int x;
62     int update_lba = 0;
63
64     while ((x = getopt (argc, argv, "vthl:i:")) != EOF) {
65         switch (x) {
66             case 'h':
67                 return usage();
68             case 'l':
69                 layout_conf = optarg;
70                 break;
71             case 't':
72                 *test = 1;
73                 break;
74             case 'i':
75                 img_file = optarg;
76                 break;
77             case 'v':
78                 *verbose = 1;
79                 break;
80             default:
81                 fprintf(stderr, "Unknown argument: %c\n", (char)optopt);
82                 return usage();
83         }
84     }
85
86     if (!img_file || !layout_conf) {
87         fprintf(stderr, "Image filename and configuration file are required\n");
88         return usage();
89     }
90
91     /* we'll need to parse the command line later for partition-file
92      * mappings, so make sure there's at least something there */
93     if (optind >= argc) {
94         fprintf(stderr, "Must provide partition -> file mappings\n");
95         return usage();
96     }
97
98     if (stat(img_file, &filestat)) {
99         perror("Cannot stat image file");
100         return 1;
101     }
102
103     /* make sure we don't screw up and write to a block device on the host
104      * and wedge things. I just don't trust myself. */
105     if (!S_ISREG(filestat.st_mode)) {
106         fprintf(stderr, "This program should only be used on regular files.");
107         return 1;
108     }
109
110     /* load the disk layout file */
111     if (!(*dinfo = load_diskconfig(layout_conf, img_file))) {
112         fprintf(stderr, "Errors encountered while loading disk conf file %s",
113                 layout_conf);
114         return 1;
115     }
116
117     if ((*dinfo)->num_lba == 0) {
118         (*dinfo)->num_lba = (*dinfo)->skip_lba + EXTRA_LBAS;
119         update_lba = 1;
120     }
121
122     /* parse the filename->partition mappings from the command line and patch
123      * up a loaded config file's partition table entries to have
124      * length == filesize */
125     x = 0;
126     while (optind < argc) {
127         char *pair = argv[optind++];
128         char *part_name;
129         struct part_info *pinfo;
130         struct stat tmp_stat;
131
132         if (x >= MAX_NUM_PARTS) {
133             fprintf(stderr, "Error: Too many partitions specified (%d)!\n", x);
134             return 1;
135         }
136
137         if (!(part_name = strsep(&pair, "=")) || !pair || !(*pair)) {
138             fprintf(stderr, "Error parsing partition mappings\n");
139             return usage();
140         }
141
142         if (!(pinfo = find_part(*dinfo, part_name))) {
143             fprintf(stderr, "Partition '%s' not found.\n", part_name);
144             return 1;
145         }
146
147         /* here pair points to the filename (after the '=') */
148         part_file_map[x].pinfo = pinfo;
149         part_file_map[x++].filename = pair;
150
151         if (stat(pair, &tmp_stat) < 0) {
152             fprintf(stderr, "Could not stat file: %s\n", pair);
153             return 1;
154         }
155
156         pinfo->len_kb = (uint32_t) ((tmp_stat.st_size + 1023) >> 10);
157         if (update_lba)
158             (*dinfo)->num_lba +=
159                     ((uint64_t)pinfo->len_kb * 1024) / (*dinfo)->sect_size;
160         printf("Updated %s length to be %uKB\n", pinfo->name, pinfo->len_kb);
161     }
162
163     return 0;
164 }
165
166 int
167 main(int argc, char *argv[])
168 {
169     struct disk_info *dinfo = NULL;
170     int test = 0;
171     int verbose = 0;
172     int cnt;
173
174     if (parse_args(argc, argv, &dinfo, &test, &verbose))
175         return 1;
176
177     if (verbose)
178         dump_disk_config(dinfo);
179
180     if (test)
181         printf("Test mode enabled. Actions will not be committed to disk!\n");
182
183     if (apply_disk_config(dinfo, test)) {
184         fprintf(stderr, "Could not apply disk configuration!\n");
185         return 1;
186     }
187
188     printf("Copying images to specified partition offsets\n");
189     /* now copy the images to their appropriate locations on disk */
190     for (cnt = 0; cnt < MAX_NUM_PARTS && part_file_map[cnt].pinfo; ++cnt) {
191         loff_t offs = part_file_map[cnt].pinfo->start_lba * dinfo->sect_size;
192         const char *dest_fn = dinfo->device;
193         if (write_raw_image(dest_fn, part_file_map[cnt].filename, offs, test)) {
194             fprintf(stderr, "Could not write images after editing label.\n");
195             return 1;
196         }
197     }
198     printf("File edit complete. Wrote %d images.\n", cnt);
199
200     return 0;
201 }