• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 <ctype.h>
18 #include <errno.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/mount.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <time.h>
30 #include <selinux/selinux.h>
31 #include <ftw.h>
32 #include <sys/capability.h>
33 #include <sys/xattr.h>
34 #include <linux/xattr.h>
35 #include <inttypes.h>
36 
37 #include <memory>
38 #include <string>
39 #include <vector>
40 
41 #include <android-base/file.h>
42 #include <android-base/parseint.h>
43 #include <android-base/strings.h>
44 #include <android-base/stringprintf.h>
45 
46 #include "bootloader.h"
47 #include "applypatch/applypatch.h"
48 #include "cutils/android_reboot.h"
49 #include "cutils/misc.h"
50 #include "cutils/properties.h"
51 #include "edify/expr.h"
52 #include "error_code.h"
53 #include "minzip/DirUtil.h"
54 #include "mtdutils/mounts.h"
55 #include "mtdutils/mtdutils.h"
56 #include "openssl/sha.h"
57 #include "ota_io.h"
58 #include "updater.h"
59 #include "install.h"
60 #include "tune2fs.h"
61 
62 #ifdef USE_EXT4
63 #include "make_ext4fs.h"
64 #include "wipe.h"
65 #endif
66 
67 // Send over the buffer to recovery though the command pipe.
uiPrint(State * state,const std::string & buffer)68 static void uiPrint(State* state, const std::string& buffer) {
69     UpdaterInfo* ui = reinterpret_cast<UpdaterInfo*>(state->cookie);
70 
71     // "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "".
72     // So skip sending empty strings to UI.
73     std::vector<std::string> lines = android::base::Split(buffer, "\n");
74     for (auto& line: lines) {
75         if (!line.empty()) {
76             fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str());
77             fprintf(ui->cmd_pipe, "ui_print\n");
78         }
79     }
80 
81     // On the updater side, we need to dump the contents to stderr (which has
82     // been redirected to the log file). Because the recovery will only print
83     // the contents to screen when processing pipe command ui_print.
84     fprintf(stderr, "%s", buffer.c_str());
85 }
86 
87 __attribute__((__format__(printf, 2, 3))) __nonnull((2))
uiPrintf(State * state,const char * format,...)88 void uiPrintf(State* state, const char* format, ...) {
89     std::string error_msg;
90 
91     va_list ap;
92     va_start(ap, format);
93     android::base::StringAppendV(&error_msg, format, ap);
94     va_end(ap);
95 
96     uiPrint(state, error_msg);
97 }
98 
99 // Take a sha-1 digest and return it as a newly-allocated hex string.
PrintSha1(const uint8_t * digest)100 char* PrintSha1(const uint8_t* digest) {
101     char* buffer = reinterpret_cast<char*>(malloc(SHA_DIGEST_LENGTH*2 + 1));
102     const char* alphabet = "0123456789abcdef";
103     size_t i;
104     for (i = 0; i < SHA_DIGEST_LENGTH; ++i) {
105         buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf];
106         buffer[i*2+1] = alphabet[digest[i] & 0xf];
107     }
108     buffer[i*2] = '\0';
109     return buffer;
110 }
111 
112 // mount(fs_type, partition_type, location, mount_point)
113 //
114 //    fs_type="yaffs2" partition_type="MTD"     location=partition
115 //    fs_type="ext4"   partition_type="EMMC"    location=device
MountFn(const char * name,State * state,int argc,Expr * argv[])116 Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
117     char* result = NULL;
118     if (argc != 4 && argc != 5) {
119         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc);
120     }
121     char* fs_type;
122     char* partition_type;
123     char* location;
124     char* mount_point;
125     char* mount_options;
126     bool has_mount_options;
127     if (argc == 5) {
128         has_mount_options = true;
129         if (ReadArgs(state, argv, 5, &fs_type, &partition_type,
130                  &location, &mount_point, &mount_options) < 0) {
131             return NULL;
132         }
133     } else {
134         has_mount_options = false;
135         if (ReadArgs(state, argv, 4, &fs_type, &partition_type,
136                  &location, &mount_point) < 0) {
137             return NULL;
138         }
139     }
140 
141     if (strlen(fs_type) == 0) {
142         ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
143         goto done;
144     }
145     if (strlen(partition_type) == 0) {
146         ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
147                    name);
148         goto done;
149     }
150     if (strlen(location) == 0) {
151         ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
152         goto done;
153     }
154     if (strlen(mount_point) == 0) {
155         ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
156                    name);
157         goto done;
158     }
159 
160     {
161         char *secontext = NULL;
162 
163         if (sehandle) {
164             selabel_lookup(sehandle, &secontext, mount_point, 0755);
165             setfscreatecon(secontext);
166         }
167 
168         mkdir(mount_point, 0755);
169 
170         if (secontext) {
171             freecon(secontext);
172             setfscreatecon(NULL);
173         }
174     }
175 
176     if (strcmp(partition_type, "MTD") == 0) {
177         mtd_scan_partitions();
178         const MtdPartition* mtd;
179         mtd = mtd_find_partition_by_name(location);
180         if (mtd == NULL) {
181             uiPrintf(state, "%s: no mtd partition named \"%s\"\n",
182                     name, location);
183             result = strdup("");
184             goto done;
185         }
186         if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) {
187             uiPrintf(state, "mtd mount of %s failed: %s\n",
188                     location, strerror(errno));
189             result = strdup("");
190             goto done;
191         }
192         result = mount_point;
193     } else {
194         if (mount(location, mount_point, fs_type,
195                   MS_NOATIME | MS_NODEV | MS_NODIRATIME,
196                   has_mount_options ? mount_options : "") < 0) {
197             uiPrintf(state, "%s: failed to mount %s at %s: %s\n",
198                     name, location, mount_point, strerror(errno));
199             result = strdup("");
200         } else {
201             result = mount_point;
202         }
203     }
204 
205 done:
206     free(fs_type);
207     free(partition_type);
208     free(location);
209     if (result != mount_point) free(mount_point);
210     if (has_mount_options) free(mount_options);
211     return StringValue(result);
212 }
213 
214 
215 // is_mounted(mount_point)
IsMountedFn(const char * name,State * state,int argc,Expr * argv[])216 Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) {
217     char* result = NULL;
218     if (argc != 1) {
219         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
220     }
221     char* mount_point;
222     if (ReadArgs(state, argv, 1, &mount_point) < 0) {
223         return NULL;
224     }
225     if (strlen(mount_point) == 0) {
226         ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty");
227         goto done;
228     }
229 
230     scan_mounted_volumes();
231     {
232         const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point);
233         if (vol == NULL) {
234             result = strdup("");
235         } else {
236             result = mount_point;
237         }
238     }
239 
240 done:
241     if (result != mount_point) free(mount_point);
242     return StringValue(result);
243 }
244 
245 
UnmountFn(const char * name,State * state,int argc,Expr * argv[])246 Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
247     char* result = NULL;
248     if (argc != 1) {
249         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
250     }
251     char* mount_point;
252     if (ReadArgs(state, argv, 1, &mount_point) < 0) {
253         return NULL;
254     }
255     if (strlen(mount_point) == 0) {
256         ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty");
257         goto done;
258     }
259 
260     scan_mounted_volumes();
261     {
262         const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point);
263         if (vol == NULL) {
264             uiPrintf(state, "unmount of %s failed; no such volume\n", mount_point);
265             result = strdup("");
266         } else {
267             int ret = unmount_mounted_volume(vol);
268             if (ret != 0) {
269                 uiPrintf(state, "unmount of %s failed (%d): %s\n",
270                          mount_point, ret, strerror(errno));
271             }
272             result = mount_point;
273         }
274     }
275 
276 done:
277     if (result != mount_point) free(mount_point);
278     return StringValue(result);
279 }
280 
exec_cmd(const char * path,char * const argv[])281 static int exec_cmd(const char* path, char* const argv[]) {
282     int status;
283     pid_t child;
284     if ((child = vfork()) == 0) {
285         execv(path, argv);
286         _exit(-1);
287     }
288     waitpid(child, &status, 0);
289     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
290         printf("%s failed with status %d\n", path, WEXITSTATUS(status));
291     }
292     return WEXITSTATUS(status);
293 }
294 
295 
296 // format(fs_type, partition_type, location, fs_size, mount_point)
297 //
298 //    fs_type="yaffs2" partition_type="MTD"     location=partition fs_size=<bytes> mount_point=<location>
299 //    fs_type="ext4"   partition_type="EMMC"    location=device    fs_size=<bytes> mount_point=<location>
300 //    fs_type="f2fs"   partition_type="EMMC"    location=device    fs_size=<bytes> mount_point=<location>
301 //    if fs_size == 0, then make fs uses the entire partition.
302 //    if fs_size > 0, that is the size to use
303 //    if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs")
FormatFn(const char * name,State * state,int argc,Expr * argv[])304 Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
305     char* result = NULL;
306     if (argc != 5) {
307         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc);
308     }
309     char* fs_type;
310     char* partition_type;
311     char* location;
312     char* fs_size;
313     char* mount_point;
314 
315     if (ReadArgs(state, argv, 5, &fs_type, &partition_type, &location, &fs_size, &mount_point) < 0) {
316         return NULL;
317     }
318 
319     if (strlen(fs_type) == 0) {
320         ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
321         goto done;
322     }
323     if (strlen(partition_type) == 0) {
324         ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
325                    name);
326         goto done;
327     }
328     if (strlen(location) == 0) {
329         ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
330         goto done;
331     }
332 
333     if (strlen(mount_point) == 0) {
334         ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
335                    name);
336         goto done;
337     }
338 
339     if (strcmp(partition_type, "MTD") == 0) {
340         mtd_scan_partitions();
341         const MtdPartition* mtd = mtd_find_partition_by_name(location);
342         if (mtd == NULL) {
343             printf("%s: no mtd partition named \"%s\"",
344                     name, location);
345             result = strdup("");
346             goto done;
347         }
348         MtdWriteContext* ctx = mtd_write_partition(mtd);
349         if (ctx == NULL) {
350             printf("%s: can't write \"%s\"", name, location);
351             result = strdup("");
352             goto done;
353         }
354         if (mtd_erase_blocks(ctx, -1) == -1) {
355             mtd_write_close(ctx);
356             printf("%s: failed to erase \"%s\"", name, location);
357             result = strdup("");
358             goto done;
359         }
360         if (mtd_write_close(ctx) != 0) {
361             printf("%s: failed to close \"%s\"", name, location);
362             result = strdup("");
363             goto done;
364         }
365         result = location;
366 #ifdef USE_EXT4
367     } else if (strcmp(fs_type, "ext4") == 0) {
368         int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle);
369         if (status != 0) {
370             printf("%s: make_ext4fs failed (%d) on %s",
371                     name, status, location);
372             result = strdup("");
373             goto done;
374         }
375         result = location;
376     } else if (strcmp(fs_type, "f2fs") == 0) {
377         char *num_sectors;
378         if (asprintf(&num_sectors, "%lld", atoll(fs_size) / 512) <= 0) {
379             printf("format_volume: failed to create %s command for %s\n", fs_type, location);
380             result = strdup("");
381             goto done;
382         }
383         const char *f2fs_path = "/sbin/mkfs.f2fs";
384         const char* const f2fs_argv[] = {"mkfs.f2fs", "-t", "-d1", location, num_sectors, NULL};
385         int status = exec_cmd(f2fs_path, (char* const*)f2fs_argv);
386         free(num_sectors);
387         if (status != 0) {
388             printf("%s: mkfs.f2fs failed (%d) on %s",
389                     name, status, location);
390             result = strdup("");
391             goto done;
392         }
393         result = location;
394 #endif
395     } else {
396         printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"",
397                 name, fs_type, partition_type);
398     }
399 
400 done:
401     free(fs_type);
402     free(partition_type);
403     if (result != location) free(location);
404     return StringValue(result);
405 }
406 
RenameFn(const char * name,State * state,int argc,Expr * argv[])407 Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
408     char* result = NULL;
409     if (argc != 2) {
410         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
411     }
412 
413     char* src_name;
414     char* dst_name;
415 
416     if (ReadArgs(state, argv, 2, &src_name, &dst_name) < 0) {
417         return NULL;
418     }
419     if (strlen(src_name) == 0) {
420         ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name);
421         goto done;
422     }
423     if (strlen(dst_name) == 0) {
424         ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name);
425         goto done;
426     }
427     if (make_parents(dst_name) != 0) {
428         ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s",
429           dst_name, strerror(errno));
430     } else if (access(dst_name, F_OK) == 0 && access(src_name, F_OK) != 0) {
431         // File was already moved
432         result = dst_name;
433     } else if (rename(src_name, dst_name) != 0) {
434         ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s",
435           src_name, dst_name, strerror(errno));
436     } else {
437         result = dst_name;
438     }
439 
440 done:
441     free(src_name);
442     if (result != dst_name) free(dst_name);
443     return StringValue(result);
444 }
445 
DeleteFn(const char * name,State * state,int argc,Expr * argv[])446 Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
447     char** paths = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
448     for (int i = 0; i < argc; ++i) {
449         paths[i] = Evaluate(state, argv[i]);
450         if (paths[i] == NULL) {
451             for (int j = 0; j < i; ++j) {
452                 free(paths[j]);
453             }
454             free(paths);
455             return NULL;
456         }
457     }
458 
459     bool recursive = (strcmp(name, "delete_recursive") == 0);
460 
461     int success = 0;
462     for (int i = 0; i < argc; ++i) {
463         if ((recursive ? dirUnlinkHierarchy(paths[i]) : unlink(paths[i])) == 0)
464             ++success;
465         free(paths[i]);
466     }
467     free(paths);
468 
469     char buffer[10];
470     sprintf(buffer, "%d", success);
471     return StringValue(strdup(buffer));
472 }
473 
474 
ShowProgressFn(const char * name,State * state,int argc,Expr * argv[])475 Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
476     if (argc != 2) {
477         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
478     }
479     char* frac_str;
480     char* sec_str;
481     if (ReadArgs(state, argv, 2, &frac_str, &sec_str) < 0) {
482         return NULL;
483     }
484 
485     double frac = strtod(frac_str, NULL);
486     int sec;
487     android::base::ParseInt(sec_str, &sec);
488 
489     UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
490     fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec);
491 
492     free(sec_str);
493     return StringValue(frac_str);
494 }
495 
SetProgressFn(const char * name,State * state,int argc,Expr * argv[])496 Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
497     if (argc != 1) {
498         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
499     }
500     char* frac_str;
501     if (ReadArgs(state, argv, 1, &frac_str) < 0) {
502         return NULL;
503     }
504 
505     double frac = strtod(frac_str, NULL);
506 
507     UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
508     fprintf(ui->cmd_pipe, "set_progress %f\n", frac);
509 
510     return StringValue(frac_str);
511 }
512 
513 // package_extract_dir(package_path, destination_path)
PackageExtractDirFn(const char * name,State * state,int argc,Expr * argv[])514 Value* PackageExtractDirFn(const char* name, State* state,
515                           int argc, Expr* argv[]) {
516     if (argc != 2) {
517         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
518     }
519     char* zip_path;
520     char* dest_path;
521     if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL;
522 
523     ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
524 
525     // To create a consistent system image, never use the clock for timestamps.
526     struct utimbuf timestamp = { 1217592000, 1217592000 };  // 8/1/2008 default
527 
528     bool success = mzExtractRecursive(za, zip_path, dest_path,
529                                       &timestamp,
530                                       NULL, NULL, sehandle);
531     free(zip_path);
532     free(dest_path);
533     return StringValue(strdup(success ? "t" : ""));
534 }
535 
536 
537 // package_extract_file(package_path, destination_path)
538 //   or
539 // package_extract_file(package_path)
540 //   to return the entire contents of the file as the result of this
541 //   function (the char* returned is actually a FileContents*).
PackageExtractFileFn(const char * name,State * state,int argc,Expr * argv[])542 Value* PackageExtractFileFn(const char* name, State* state,
543                            int argc, Expr* argv[]) {
544     if (argc < 1 || argc > 2) {
545         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d",
546                           name, argc);
547     }
548     bool success = false;
549 
550     if (argc == 2) {
551         // The two-argument version extracts to a file.
552 
553         ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
554 
555         char* zip_path;
556         char* dest_path;
557         if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL;
558 
559         const ZipEntry* entry = mzFindZipEntry(za, zip_path);
560         if (entry == NULL) {
561             printf("%s: no %s in package\n", name, zip_path);
562             goto done2;
563         }
564 
565         {
566             int fd = TEMP_FAILURE_RETRY(ota_open(dest_path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
567                   S_IRUSR | S_IWUSR));
568             if (fd == -1) {
569                 printf("%s: can't open %s for write: %s\n", name, dest_path, strerror(errno));
570                 goto done2;
571             }
572             success = mzExtractZipEntryToFile(za, entry, fd);
573             if (ota_fsync(fd) == -1) {
574                 printf("fsync of \"%s\" failed: %s\n", dest_path, strerror(errno));
575                 success = false;
576             }
577             if (ota_close(fd) == -1) {
578                 printf("close of \"%s\" failed: %s\n", dest_path, strerror(errno));
579                 success = false;
580             }
581         }
582 
583       done2:
584         free(zip_path);
585         free(dest_path);
586         return StringValue(strdup(success ? "t" : ""));
587     } else {
588         // The one-argument version returns the contents of the file
589         // as the result.
590 
591         char* zip_path;
592         if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL;
593 
594         Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value)));
595         v->type = VAL_BLOB;
596         v->size = -1;
597         v->data = NULL;
598 
599         ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
600         const ZipEntry* entry = mzFindZipEntry(za, zip_path);
601         if (entry == NULL) {
602             printf("%s: no %s in package\n", name, zip_path);
603             goto done1;
604         }
605 
606         v->size = mzGetZipEntryUncompLen(entry);
607         v->data = reinterpret_cast<char*>(malloc(v->size));
608         if (v->data == NULL) {
609             printf("%s: failed to allocate %ld bytes for %s\n",
610                     name, (long)v->size, zip_path);
611             goto done1;
612         }
613 
614         success = mzExtractZipEntryToBuffer(za, entry,
615                                             (unsigned char *)v->data);
616 
617       done1:
618         free(zip_path);
619         if (!success) {
620             free(v->data);
621             v->data = NULL;
622             v->size = -1;
623         }
624         return v;
625     }
626 }
627 
628 // Create all parent directories of name, if necessary.
make_parents(char * name)629 static int make_parents(char* name) {
630     char* p;
631     for (p = name + (strlen(name)-1); p > name; --p) {
632         if (*p != '/') continue;
633         *p = '\0';
634         if (make_parents(name) < 0) return -1;
635         int result = mkdir(name, 0700);
636         if (result == 0) printf("created [%s]\n", name);
637         *p = '/';
638         if (result == 0 || errno == EEXIST) {
639             // successfully created or already existed; we're done
640             return 0;
641         } else {
642             printf("failed to mkdir %s: %s\n", name, strerror(errno));
643             return -1;
644         }
645     }
646     return 0;
647 }
648 
649 // symlink target src1 src2 ...
650 //    unlinks any previously existing src1, src2, etc before creating symlinks.
SymlinkFn(const char * name,State * state,int argc,Expr * argv[])651 Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
652     if (argc == 0) {
653         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc);
654     }
655     char* target;
656     target = Evaluate(state, argv[0]);
657     if (target == NULL) return NULL;
658 
659     char** srcs = ReadVarArgs(state, argc-1, argv+1);
660     if (srcs == NULL) {
661         free(target);
662         return NULL;
663     }
664 
665     int bad = 0;
666     int i;
667     for (i = 0; i < argc-1; ++i) {
668         if (unlink(srcs[i]) < 0) {
669             if (errno != ENOENT) {
670                 printf("%s: failed to remove %s: %s\n",
671                         name, srcs[i], strerror(errno));
672                 ++bad;
673             }
674         }
675         if (make_parents(srcs[i])) {
676             printf("%s: failed to symlink %s to %s: making parents failed\n",
677                     name, srcs[i], target);
678             ++bad;
679         }
680         if (symlink(target, srcs[i]) < 0) {
681             printf("%s: failed to symlink %s to %s: %s\n",
682                     name, srcs[i], target, strerror(errno));
683             ++bad;
684         }
685         free(srcs[i]);
686     }
687     free(srcs);
688     if (bad) {
689         return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name);
690     }
691     return StringValue(strdup(""));
692 }
693 
694 struct perm_parsed_args {
695     bool has_uid;
696     uid_t uid;
697     bool has_gid;
698     gid_t gid;
699     bool has_mode;
700     mode_t mode;
701     bool has_fmode;
702     mode_t fmode;
703     bool has_dmode;
704     mode_t dmode;
705     bool has_selabel;
706     char* selabel;
707     bool has_capabilities;
708     uint64_t capabilities;
709 };
710 
ParsePermArgs(State * state,int argc,char ** args)711 static struct perm_parsed_args ParsePermArgs(State * state, int argc, char** args) {
712     int i;
713     struct perm_parsed_args parsed;
714     int bad = 0;
715     static int max_warnings = 20;
716 
717     memset(&parsed, 0, sizeof(parsed));
718 
719     for (i = 1; i < argc; i += 2) {
720         if (strcmp("uid", args[i]) == 0) {
721             int64_t uid;
722             if (sscanf(args[i+1], "%" SCNd64, &uid) == 1) {
723                 parsed.uid = uid;
724                 parsed.has_uid = true;
725             } else {
726                 uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1]);
727                 bad++;
728             }
729             continue;
730         }
731         if (strcmp("gid", args[i]) == 0) {
732             int64_t gid;
733             if (sscanf(args[i+1], "%" SCNd64, &gid) == 1) {
734                 parsed.gid = gid;
735                 parsed.has_gid = true;
736             } else {
737                 uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1]);
738                 bad++;
739             }
740             continue;
741         }
742         if (strcmp("mode", args[i]) == 0) {
743             int32_t mode;
744             if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
745                 parsed.mode = mode;
746                 parsed.has_mode = true;
747             } else {
748                 uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1]);
749                 bad++;
750             }
751             continue;
752         }
753         if (strcmp("dmode", args[i]) == 0) {
754             int32_t mode;
755             if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
756                 parsed.dmode = mode;
757                 parsed.has_dmode = true;
758             } else {
759                 uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1]);
760                 bad++;
761             }
762             continue;
763         }
764         if (strcmp("fmode", args[i]) == 0) {
765             int32_t mode;
766             if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
767                 parsed.fmode = mode;
768                 parsed.has_fmode = true;
769             } else {
770                 uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1]);
771                 bad++;
772             }
773             continue;
774         }
775         if (strcmp("capabilities", args[i]) == 0) {
776             int64_t capabilities;
777             if (sscanf(args[i+1], "%" SCNi64, &capabilities) == 1) {
778                 parsed.capabilities = capabilities;
779                 parsed.has_capabilities = true;
780             } else {
781                 uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1]);
782                 bad++;
783             }
784             continue;
785         }
786         if (strcmp("selabel", args[i]) == 0) {
787             if (args[i+1][0] != '\0') {
788                 parsed.selabel = args[i+1];
789                 parsed.has_selabel = true;
790             } else {
791                 uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1]);
792                 bad++;
793             }
794             continue;
795         }
796         if (max_warnings != 0) {
797             printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i]);
798             max_warnings--;
799             if (max_warnings == 0) {
800                 printf("ParsedPermArgs: suppressing further warnings\n");
801             }
802         }
803     }
804     return parsed;
805 }
806 
ApplyParsedPerms(State * state,const char * filename,const struct stat * statptr,struct perm_parsed_args parsed)807 static int ApplyParsedPerms(
808         State * state,
809         const char* filename,
810         const struct stat *statptr,
811         struct perm_parsed_args parsed)
812 {
813     int bad = 0;
814 
815     if (parsed.has_selabel) {
816         if (lsetfilecon(filename, parsed.selabel) != 0) {
817             uiPrintf(state, "ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n",
818                     filename, parsed.selabel, strerror(errno));
819             bad++;
820         }
821     }
822 
823     /* ignore symlinks */
824     if (S_ISLNK(statptr->st_mode)) {
825         return bad;
826     }
827 
828     if (parsed.has_uid) {
829         if (chown(filename, parsed.uid, -1) < 0) {
830             uiPrintf(state, "ApplyParsedPerms: chown of %s to %d failed: %s\n",
831                     filename, parsed.uid, strerror(errno));
832             bad++;
833         }
834     }
835 
836     if (parsed.has_gid) {
837         if (chown(filename, -1, parsed.gid) < 0) {
838             uiPrintf(state, "ApplyParsedPerms: chgrp of %s to %d failed: %s\n",
839                     filename, parsed.gid, strerror(errno));
840             bad++;
841         }
842     }
843 
844     if (parsed.has_mode) {
845         if (chmod(filename, parsed.mode) < 0) {
846             uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n",
847                     filename, parsed.mode, strerror(errno));
848             bad++;
849         }
850     }
851 
852     if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) {
853         if (chmod(filename, parsed.dmode) < 0) {
854             uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n",
855                     filename, parsed.dmode, strerror(errno));
856             bad++;
857         }
858     }
859 
860     if (parsed.has_fmode && S_ISREG(statptr->st_mode)) {
861         if (chmod(filename, parsed.fmode) < 0) {
862             uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n",
863                    filename, parsed.fmode, strerror(errno));
864             bad++;
865         }
866     }
867 
868     if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) {
869         if (parsed.capabilities == 0) {
870             if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) {
871                 // Report failure unless it's ENODATA (attribute not set)
872                 uiPrintf(state, "ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n",
873                        filename, parsed.capabilities, strerror(errno));
874                 bad++;
875             }
876         } else {
877             struct vfs_cap_data cap_data;
878             memset(&cap_data, 0, sizeof(cap_data));
879             cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
880             cap_data.data[0].permitted = (uint32_t) (parsed.capabilities & 0xffffffff);
881             cap_data.data[0].inheritable = 0;
882             cap_data.data[1].permitted = (uint32_t) (parsed.capabilities >> 32);
883             cap_data.data[1].inheritable = 0;
884             if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
885                 uiPrintf(state, "ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n",
886                         filename, parsed.capabilities, strerror(errno));
887                 bad++;
888             }
889         }
890     }
891 
892     return bad;
893 }
894 
895 // nftw doesn't allow us to pass along context, so we need to use
896 // global variables.  *sigh*
897 static struct perm_parsed_args recursive_parsed_args;
898 static State* recursive_state;
899 
do_SetMetadataRecursive(const char * filename,const struct stat * statptr,int fileflags,struct FTW * pfwt)900 static int do_SetMetadataRecursive(const char* filename, const struct stat *statptr,
901         int fileflags, struct FTW *pfwt) {
902     return ApplyParsedPerms(recursive_state, filename, statptr, recursive_parsed_args);
903 }
904 
SetMetadataFn(const char * name,State * state,int argc,Expr * argv[])905 static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) {
906     int bad = 0;
907     struct stat sb;
908     Value* result = NULL;
909 
910     bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
911 
912     if ((argc % 2) != 1) {
913         return ErrorAbort(state, kArgsParsingFailure,
914                           "%s() expects an odd number of arguments, got %d", name, argc);
915     }
916 
917     char** args = ReadVarArgs(state, argc, argv);
918     if (args == NULL) return NULL;
919 
920     if (lstat(args[0], &sb) == -1) {
921         result = ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s",
922                             name, args[0], strerror(errno));
923         goto done;
924     }
925 
926     {
927         struct perm_parsed_args parsed = ParsePermArgs(state, argc, args);
928 
929         if (recursive) {
930             recursive_parsed_args = parsed;
931             recursive_state = state;
932             bad += nftw(args[0], do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS);
933             memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args));
934             recursive_state = NULL;
935         } else {
936             bad += ApplyParsedPerms(state, args[0], &sb, parsed);
937         }
938     }
939 
940 done:
941     for (int i = 0; i < argc; ++i) {
942         free(args[i]);
943     }
944     free(args);
945 
946     if (result != NULL) {
947         return result;
948     }
949 
950     if (bad > 0) {
951         return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
952     }
953 
954     return StringValue(strdup(""));
955 }
956 
GetPropFn(const char * name,State * state,int argc,Expr * argv[])957 Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
958     if (argc != 1) {
959         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
960     }
961     char* key = Evaluate(state, argv[0]);
962     if (key == NULL) return NULL;
963 
964     char value[PROPERTY_VALUE_MAX];
965     property_get(key, value, "");
966     free(key);
967 
968     return StringValue(strdup(value));
969 }
970 
971 // file_getprop(file, key)
972 //
973 //   interprets 'file' as a getprop-style file (key=value pairs, one
974 //   per line. # comment lines,blank lines, lines without '=' ignored),
975 //   and returns the value for 'key' (or "" if it isn't defined).
FileGetPropFn(const char * name,State * state,int argc,Expr * argv[])976 Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
977     char* result = NULL;
978     char* buffer = NULL;
979     char* filename;
980     char* key;
981     if (ReadArgs(state, argv, 2, &filename, &key) < 0) {
982         return NULL;
983     }
984 
985     struct stat st;
986     if (stat(filename, &st) < 0) {
987         ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, filename,
988                    strerror(errno));
989         goto done;
990     }
991 
992 #define MAX_FILE_GETPROP_SIZE    65536
993 
994     if (st.st_size > MAX_FILE_GETPROP_SIZE) {
995         ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %d)", filename, name,
996                    MAX_FILE_GETPROP_SIZE);
997         goto done;
998     }
999 
1000     buffer = reinterpret_cast<char*>(malloc(st.st_size+1));
1001     if (buffer == NULL) {
1002         ErrorAbort(state, kFileGetPropFailure, "%s: failed to alloc %lld bytes", name,
1003                    (long long)st.st_size+1);
1004         goto done;
1005     }
1006 
1007     FILE* f;
1008     f = fopen(filename, "rb");
1009     if (f == NULL) {
1010         ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename,
1011                    strerror(errno));
1012         goto done;
1013     }
1014 
1015     if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
1016         ErrorAbort(state, kFreadFailure, "%s: failed to read %lld bytes from %s",
1017                    name, (long long)st.st_size+1, filename);
1018         fclose(f);
1019         goto done;
1020     }
1021     buffer[st.st_size] = '\0';
1022 
1023     fclose(f);
1024 
1025     char* line;
1026     line = strtok(buffer, "\n");
1027     do {
1028         // skip whitespace at start of line
1029         while (*line && isspace(*line)) ++line;
1030 
1031         // comment or blank line: skip to next line
1032         if (*line == '\0' || *line == '#') continue;
1033 
1034         char* equal = strchr(line, '=');
1035         if (equal == NULL) {
1036             continue;
1037         }
1038 
1039         // trim whitespace between key and '='
1040         char* key_end = equal-1;
1041         while (key_end > line && isspace(*key_end)) --key_end;
1042         key_end[1] = '\0';
1043 
1044         // not the key we're looking for
1045         if (strcmp(key, line) != 0) continue;
1046 
1047         // skip whitespace after the '=' to the start of the value
1048         char* val_start = equal+1;
1049         while(*val_start && isspace(*val_start)) ++val_start;
1050 
1051         // trim trailing whitespace
1052         char* val_end = val_start + strlen(val_start)-1;
1053         while (val_end > val_start && isspace(*val_end)) --val_end;
1054         val_end[1] = '\0';
1055 
1056         result = strdup(val_start);
1057         break;
1058 
1059     } while ((line = strtok(NULL, "\n")));
1060 
1061     if (result == NULL) result = strdup("");
1062 
1063   done:
1064     free(filename);
1065     free(key);
1066     free(buffer);
1067     return StringValue(result);
1068 }
1069 
1070 // write_raw_image(filename_or_blob, partition)
WriteRawImageFn(const char * name,State * state,int argc,Expr * argv[])1071 Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
1072     char* result = NULL;
1073 
1074     Value* partition_value;
1075     Value* contents;
1076     if (ReadValueArgs(state, argv, 2, &contents, &partition_value) < 0) {
1077         return NULL;
1078     }
1079 
1080     char* partition = NULL;
1081     if (partition_value->type != VAL_STRING) {
1082         ErrorAbort(state, kArgsParsingFailure, "partition argument to %s must be string", name);
1083         goto done;
1084     }
1085     partition = partition_value->data;
1086     if (strlen(partition) == 0) {
1087         ErrorAbort(state, kArgsParsingFailure, "partition argument to %s can't be empty", name);
1088         goto done;
1089     }
1090     if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) {
1091         ErrorAbort(state, kArgsParsingFailure, "file argument to %s can't be empty", name);
1092         goto done;
1093     }
1094 
1095     mtd_scan_partitions();
1096     const MtdPartition* mtd;
1097     mtd = mtd_find_partition_by_name(partition);
1098     if (mtd == NULL) {
1099         printf("%s: no mtd partition named \"%s\"\n", name, partition);
1100         result = strdup("");
1101         goto done;
1102     }
1103 
1104     MtdWriteContext* ctx;
1105     ctx = mtd_write_partition(mtd);
1106     if (ctx == NULL) {
1107         printf("%s: can't write mtd partition \"%s\"\n",
1108                 name, partition);
1109         result = strdup("");
1110         goto done;
1111     }
1112 
1113     bool success;
1114 
1115     if (contents->type == VAL_STRING) {
1116         // we're given a filename as the contents
1117         char* filename = contents->data;
1118         FILE* f = ota_fopen(filename, "rb");
1119         if (f == NULL) {
1120             printf("%s: can't open %s: %s\n", name, filename, strerror(errno));
1121             result = strdup("");
1122             goto done;
1123         }
1124 
1125         success = true;
1126         char* buffer = reinterpret_cast<char*>(malloc(BUFSIZ));
1127         int read;
1128         while (success && (read = ota_fread(buffer, 1, BUFSIZ, f)) > 0) {
1129             int wrote = mtd_write_data(ctx, buffer, read);
1130             success = success && (wrote == read);
1131         }
1132         free(buffer);
1133         ota_fclose(f);
1134     } else {
1135         // we're given a blob as the contents
1136         ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size);
1137         success = (wrote == contents->size);
1138     }
1139     if (!success) {
1140         printf("mtd_write_data to %s failed: %s\n",
1141                 partition, strerror(errno));
1142     }
1143 
1144     if (mtd_erase_blocks(ctx, -1) == -1) {
1145         printf("%s: error erasing blocks of %s\n", name, partition);
1146     }
1147     if (mtd_write_close(ctx) != 0) {
1148         printf("%s: error closing write of %s\n", name, partition);
1149     }
1150 
1151     printf("%s %s partition\n",
1152            success ? "wrote" : "failed to write", partition);
1153 
1154     result = success ? partition : strdup("");
1155 
1156 done:
1157     if (result != partition) FreeValue(partition_value);
1158     FreeValue(contents);
1159     return StringValue(result);
1160 }
1161 
1162 // apply_patch_space(bytes)
ApplyPatchSpaceFn(const char * name,State * state,int argc,Expr * argv[])1163 Value* ApplyPatchSpaceFn(const char* name, State* state,
1164                          int argc, Expr* argv[]) {
1165     char* bytes_str;
1166     if (ReadArgs(state, argv, 1, &bytes_str) < 0) {
1167         return NULL;
1168     }
1169 
1170     size_t bytes;
1171     if (!android::base::ParseUint(bytes_str, &bytes)) {
1172         ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n",
1173                    name, bytes_str);
1174         free(bytes_str);
1175         return nullptr;
1176     }
1177 
1178     return StringValue(strdup(CacheSizeCheck(bytes) ? "" : "t"));
1179 }
1180 
1181 // apply_patch(file, size, init_sha1, tgt_sha1, patch)
1182 
ApplyPatchFn(const char * name,State * state,int argc,Expr * argv[])1183 Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
1184     if (argc < 6 || (argc % 2) == 1) {
1185         return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an "
1186                                  "even number, got %d", name, argc);
1187     }
1188 
1189     char* source_filename;
1190     char* target_filename;
1191     char* target_sha1;
1192     char* target_size_str;
1193     if (ReadArgs(state, argv, 4, &source_filename, &target_filename,
1194                  &target_sha1, &target_size_str) < 0) {
1195         return NULL;
1196     }
1197 
1198     size_t target_size;
1199     if (!android::base::ParseUint(target_size_str, &target_size)) {
1200         ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count",
1201                    name, target_size_str);
1202         free(source_filename);
1203         free(target_filename);
1204         free(target_sha1);
1205         free(target_size_str);
1206         return nullptr;
1207     }
1208 
1209     int patchcount = (argc-4) / 2;
1210     std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc-4, argv+4),
1211                                                         free);
1212     if (!arg_values) {
1213         return nullptr;
1214     }
1215     std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patch_shas;
1216     std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches;
1217     // Protect values by unique_ptrs first to get rid of memory leak.
1218     for (int i = 0; i < patchcount * 2; i += 2) {
1219         patch_shas.emplace_back(arg_values.get()[i], FreeValue);
1220         patches.emplace_back(arg_values.get()[i+1], FreeValue);
1221     }
1222 
1223     for (int i = 0; i < patchcount; ++i) {
1224         if (patch_shas[i]->type != VAL_STRING) {
1225             ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, i);
1226             return nullptr;
1227         }
1228         if (patches[i]->type != VAL_BLOB) {
1229             ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, i);
1230             return nullptr;
1231         }
1232     }
1233 
1234     std::vector<char*> patch_sha_str;
1235     std::vector<Value*> patch_ptrs;
1236     for (int i = 0; i < patchcount; ++i) {
1237         patch_sha_str.push_back(patch_shas[i]->data);
1238         patch_ptrs.push_back(patches[i].get());
1239     }
1240 
1241     int result = applypatch(source_filename, target_filename,
1242                             target_sha1, target_size,
1243                             patchcount, patch_sha_str.data(), patch_ptrs.data(), NULL);
1244 
1245     return StringValue(strdup(result == 0 ? "t" : ""));
1246 }
1247 
1248 // apply_patch_check(file, [sha1_1, ...])
ApplyPatchCheckFn(const char * name,State * state,int argc,Expr * argv[])1249 Value* ApplyPatchCheckFn(const char* name, State* state,
1250                          int argc, Expr* argv[]) {
1251     if (argc < 1) {
1252         return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d",
1253                           name, argc);
1254     }
1255 
1256     char* filename;
1257     if (ReadArgs(state, argv, 1, &filename) < 0) {
1258         return NULL;
1259     }
1260 
1261     int patchcount = argc-1;
1262     char** sha1s = ReadVarArgs(state, argc-1, argv+1);
1263 
1264     int result = applypatch_check(filename, patchcount, sha1s);
1265 
1266     int i;
1267     for (i = 0; i < patchcount; ++i) {
1268         free(sha1s[i]);
1269     }
1270     free(sha1s);
1271 
1272     return StringValue(strdup(result == 0 ? "t" : ""));
1273 }
1274 
1275 // This is the updater side handler for ui_print() in edify script. Contents
1276 // will be sent over to the recovery side for on-screen display.
UIPrintFn(const char * name,State * state,int argc,Expr * argv[])1277 Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
1278     char** args = ReadVarArgs(state, argc, argv);
1279     if (args == NULL) {
1280         return NULL;
1281     }
1282 
1283     std::string buffer;
1284     for (int i = 0; i < argc; ++i) {
1285         buffer += args[i];
1286         free(args[i]);
1287     }
1288     free(args);
1289 
1290     buffer += "\n";
1291     uiPrint(state, buffer);
1292     return StringValue(strdup(buffer.c_str()));
1293 }
1294 
WipeCacheFn(const char * name,State * state,int argc,Expr * argv[])1295 Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
1296     if (argc != 0) {
1297         return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
1298     }
1299     fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n");
1300     return StringValue(strdup("t"));
1301 }
1302 
RunProgramFn(const char * name,State * state,int argc,Expr * argv[])1303 Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
1304     if (argc < 1) {
1305         return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
1306     }
1307     char** args = ReadVarArgs(state, argc, argv);
1308     if (args == NULL) {
1309         return NULL;
1310     }
1311 
1312     char** args2 = reinterpret_cast<char**>(malloc(sizeof(char*) * (argc+1)));
1313     memcpy(args2, args, sizeof(char*) * argc);
1314     args2[argc] = NULL;
1315 
1316     printf("about to run program [%s] with %d args\n", args2[0], argc);
1317 
1318     pid_t child = fork();
1319     if (child == 0) {
1320         execv(args2[0], args2);
1321         printf("run_program: execv failed: %s\n", strerror(errno));
1322         _exit(1);
1323     }
1324     int status;
1325     waitpid(child, &status, 0);
1326     if (WIFEXITED(status)) {
1327         if (WEXITSTATUS(status) != 0) {
1328             printf("run_program: child exited with status %d\n",
1329                     WEXITSTATUS(status));
1330         }
1331     } else if (WIFSIGNALED(status)) {
1332         printf("run_program: child terminated by signal %d\n",
1333                 WTERMSIG(status));
1334     }
1335 
1336     int i;
1337     for (i = 0; i < argc; ++i) {
1338         free(args[i]);
1339     }
1340     free(args);
1341     free(args2);
1342 
1343     char buffer[20];
1344     sprintf(buffer, "%d", status);
1345 
1346     return StringValue(strdup(buffer));
1347 }
1348 
1349 // sha1_check(data)
1350 //    to return the sha1 of the data (given in the format returned by
1351 //    read_file).
1352 //
1353 // sha1_check(data, sha1_hex, [sha1_hex, ...])
1354 //    returns the sha1 of the file if it matches any of the hex
1355 //    strings passed, or "" if it does not equal any of them.
1356 //
Sha1CheckFn(const char * name,State * state,int argc,Expr * argv[])1357 Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
1358     if (argc < 1) {
1359         return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
1360     }
1361 
1362     std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free);
1363     if (arg_values == nullptr) {
1364         return nullptr;
1365     }
1366     std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> args;
1367     for (int i = 0; i < argc; ++i) {
1368         args.emplace_back(arg_values.get()[i], FreeValue);
1369     }
1370 
1371     if (args[0]->size < 0) {
1372         return StringValue(strdup(""));
1373     }
1374     uint8_t digest[SHA_DIGEST_LENGTH];
1375     SHA1(reinterpret_cast<uint8_t*>(args[0]->data), args[0]->size, digest);
1376 
1377     if (argc == 1) {
1378         return StringValue(PrintSha1(digest));
1379     }
1380 
1381     int i;
1382     uint8_t arg_digest[SHA_DIGEST_LENGTH];
1383     for (i = 1; i < argc; ++i) {
1384         if (args[i]->type != VAL_STRING) {
1385             printf("%s(): arg %d is not a string; skipping",
1386                     name, i);
1387         } else if (ParseSha1(args[i]->data, arg_digest) != 0) {
1388             // Warn about bad args and skip them.
1389             printf("%s(): error parsing \"%s\" as sha-1; skipping",
1390                    name, args[i]->data);
1391         } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) {
1392             break;
1393         }
1394     }
1395     if (i >= argc) {
1396         // Didn't match any of the hex strings; return false.
1397         return StringValue(strdup(""));
1398     }
1399     // Found a match.
1400     return args[i].release();
1401 }
1402 
1403 // Read a local file and return its contents (the Value* returned
1404 // is actually a FileContents*).
ReadFileFn(const char * name,State * state,int argc,Expr * argv[])1405 Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
1406     if (argc != 1) {
1407         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
1408     }
1409     char* filename;
1410     if (ReadArgs(state, argv, 1, &filename) < 0) return NULL;
1411 
1412     Value* v = static_cast<Value*>(malloc(sizeof(Value)));
1413     if (v == nullptr) {
1414         return nullptr;
1415     }
1416     v->type = VAL_BLOB;
1417     v->size = -1;
1418     v->data = nullptr;
1419 
1420     FileContents fc;
1421     if (LoadFileContents(filename, &fc) == 0) {
1422         v->data = static_cast<char*>(malloc(fc.data.size()));
1423         if (v->data != nullptr) {
1424             memcpy(v->data, fc.data.data(), fc.data.size());
1425             v->size = fc.data.size();
1426         }
1427     }
1428     free(filename);
1429     return v;
1430 }
1431 
1432 // write_value(value, filename)
1433 //   Writes 'value' to 'filename'.
1434 //   Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
WriteValueFn(const char * name,State * state,int argc,Expr * argv[])1435 Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) {
1436     if (argc != 2) {
1437         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
1438     }
1439 
1440     char* value;
1441     char* filename;
1442     if (ReadArgs(state, argv, 2, &value, &filename) < 0) {
1443         return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)",
1444                           name);
1445     }
1446 
1447     bool ret = android::base::WriteStringToFile(value, filename);
1448     if (!ret) {
1449         printf("%s: Failed to write to \"%s\": %s\n", name, filename, strerror(errno));
1450     }
1451 
1452     free(value);
1453     free(filename);
1454     return StringValue(strdup(ret ? "t" : ""));
1455 }
1456 
1457 // Immediately reboot the device.  Recovery is not finished normally,
1458 // so if you reboot into recovery it will re-start applying the
1459 // current package (because nothing has cleared the copy of the
1460 // arguments stored in the BCB).
1461 //
1462 // The argument is the partition name passed to the android reboot
1463 // property.  It can be "recovery" to boot from the recovery
1464 // partition, or "" (empty string) to boot from the regular boot
1465 // partition.
RebootNowFn(const char * name,State * state,int argc,Expr * argv[])1466 Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
1467     if (argc != 2) {
1468         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
1469     }
1470 
1471     char* filename;
1472     char* property;
1473     if (ReadArgs(state, argv, 2, &filename, &property) < 0) return NULL;
1474 
1475     char buffer[80];
1476 
1477     // zero out the 'command' field of the bootloader message.
1478     memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command));
1479     FILE* f = fopen(filename, "r+b");
1480     fseek(f, offsetof(struct bootloader_message, command), SEEK_SET);
1481     ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f);
1482     fclose(f);
1483     free(filename);
1484 
1485     strcpy(buffer, "reboot,");
1486     if (property != NULL) {
1487         strncat(buffer, property, sizeof(buffer)-10);
1488     }
1489 
1490     property_set(ANDROID_RB_PROPERTY, buffer);
1491 
1492     sleep(5);
1493     free(property);
1494     ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
1495     return NULL;
1496 }
1497 
1498 // Store a string value somewhere that future invocations of recovery
1499 // can access it.  This value is called the "stage" and can be used to
1500 // drive packages that need to do reboots in the middle of
1501 // installation and keep track of where they are in the multi-stage
1502 // install.
1503 //
1504 // The first argument is the block device for the misc partition
1505 // ("/misc" in the fstab), which is where this value is stored.  The
1506 // second argument is the string to store; it should not exceed 31
1507 // bytes.
SetStageFn(const char * name,State * state,int argc,Expr * argv[])1508 Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
1509     if (argc != 2) {
1510         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
1511     }
1512 
1513     char* filename;
1514     char* stagestr;
1515     if (ReadArgs(state, argv, 2, &filename, &stagestr) < 0) return NULL;
1516 
1517     // Store this value in the misc partition, immediately after the
1518     // bootloader message that the main recovery uses to save its
1519     // arguments in case of the device restarting midway through
1520     // package installation.
1521     FILE* f = fopen(filename, "r+b");
1522     fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
1523     int to_write = strlen(stagestr)+1;
1524     int max_size = sizeof(((struct bootloader_message*)0)->stage);
1525     if (to_write > max_size) {
1526         to_write = max_size;
1527         stagestr[max_size-1] = 0;
1528     }
1529     ota_fwrite(stagestr, to_write, 1, f);
1530     fclose(f);
1531 
1532     free(stagestr);
1533     return StringValue(filename);
1534 }
1535 
1536 // Return the value most recently saved with SetStageFn.  The argument
1537 // is the block device for the misc partition.
GetStageFn(const char * name,State * state,int argc,Expr * argv[])1538 Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
1539     if (argc != 1) {
1540         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
1541     }
1542 
1543     char* filename;
1544     if (ReadArgs(state, argv, 1, &filename) < 0) return NULL;
1545 
1546     char buffer[sizeof(((struct bootloader_message*)0)->stage)];
1547     FILE* f = fopen(filename, "rb");
1548     fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
1549     ota_fread(buffer, sizeof(buffer), 1, f);
1550     fclose(f);
1551     buffer[sizeof(buffer)-1] = '\0';
1552 
1553     return StringValue(strdup(buffer));
1554 }
1555 
WipeBlockDeviceFn(const char * name,State * state,int argc,Expr * argv[])1556 Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) {
1557     if (argc != 2) {
1558         return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
1559     }
1560 
1561     char* filename;
1562     char* len_str;
1563     if (ReadArgs(state, argv, 2, &filename, &len_str) < 0) return NULL;
1564 
1565     size_t len;
1566     android::base::ParseUint(len_str, &len);
1567     int fd = ota_open(filename, O_WRONLY, 0644);
1568     int success = wipe_block_device(fd, len);
1569 
1570     free(filename);
1571     free(len_str);
1572 
1573     ota_close(fd);
1574 
1575     return StringValue(strdup(success ? "t" : ""));
1576 }
1577 
EnableRebootFn(const char * name,State * state,int argc,Expr * argv[])1578 Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
1579     if (argc != 0) {
1580         return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
1581     }
1582     UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
1583     fprintf(ui->cmd_pipe, "enable_reboot\n");
1584     return StringValue(strdup("t"));
1585 }
1586 
Tune2FsFn(const char * name,State * state,int argc,Expr * argv[])1587 Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
1588     if (argc == 0) {
1589         return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc);
1590     }
1591 
1592     char** args = ReadVarArgs(state, argc, argv);
1593     if (args == NULL) {
1594         return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
1595     }
1596 
1597     char** args2 = reinterpret_cast<char**>(malloc(sizeof(char*) * (argc+1)));
1598     // Tune2fs expects the program name as its args[0]
1599     args2[0] = strdup(name);
1600     for (int i = 0; i < argc; ++i) {
1601        args2[i + 1] = args[i];
1602     }
1603     int result = tune2fs_main(argc + 1, args2);
1604     for (int i = 0; i < argc; ++i) {
1605         free(args[i]);
1606     }
1607     free(args);
1608 
1609     free(args2[0]);
1610     free(args2);
1611     if (result != 0) {
1612         return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d",
1613                           name, result);
1614     }
1615     return StringValue(strdup("t"));
1616 }
1617 
RegisterInstallFunctions()1618 void RegisterInstallFunctions() {
1619     RegisterFunction("mount", MountFn);
1620     RegisterFunction("is_mounted", IsMountedFn);
1621     RegisterFunction("unmount", UnmountFn);
1622     RegisterFunction("format", FormatFn);
1623     RegisterFunction("show_progress", ShowProgressFn);
1624     RegisterFunction("set_progress", SetProgressFn);
1625     RegisterFunction("delete", DeleteFn);
1626     RegisterFunction("delete_recursive", DeleteFn);
1627     RegisterFunction("package_extract_dir", PackageExtractDirFn);
1628     RegisterFunction("package_extract_file", PackageExtractFileFn);
1629     RegisterFunction("symlink", SymlinkFn);
1630 
1631     // Usage:
1632     //   set_metadata("filename", "key1", "value1", "key2", "value2", ...)
1633     // Example:
1634     //   set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
1635     RegisterFunction("set_metadata", SetMetadataFn);
1636 
1637     // Usage:
1638     //   set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
1639     // Example:
1640     //   set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
1641     RegisterFunction("set_metadata_recursive", SetMetadataFn);
1642 
1643     RegisterFunction("getprop", GetPropFn);
1644     RegisterFunction("file_getprop", FileGetPropFn);
1645     RegisterFunction("write_raw_image", WriteRawImageFn);
1646 
1647     RegisterFunction("apply_patch", ApplyPatchFn);
1648     RegisterFunction("apply_patch_check", ApplyPatchCheckFn);
1649     RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
1650 
1651     RegisterFunction("wipe_block_device", WipeBlockDeviceFn);
1652 
1653     RegisterFunction("read_file", ReadFileFn);
1654     RegisterFunction("sha1_check", Sha1CheckFn);
1655     RegisterFunction("rename", RenameFn);
1656     RegisterFunction("write_value", WriteValueFn);
1657 
1658     RegisterFunction("wipe_cache", WipeCacheFn);
1659 
1660     RegisterFunction("ui_print", UIPrintFn);
1661 
1662     RegisterFunction("run_program", RunProgramFn);
1663 
1664     RegisterFunction("reboot_now", RebootNowFn);
1665     RegisterFunction("get_stage", GetStageFn);
1666     RegisterFunction("set_stage", SetStageFn);
1667 
1668     RegisterFunction("enable_reboot", EnableRebootFn);
1669     RegisterFunction("tune2fs", Tune2FsFn);
1670 }
1671