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