1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sha1.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <limits.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/in.h>
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <resolv.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/dir_hash.h>
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/**
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copies, if it fits within max_output_string bytes, into output_string
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * a hash of the contents, size, permissions, uid, and gid of the file
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * specified by path, using the specified algorithm.  Returns the length
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * of the output string, or a negative number if the buffer is too short.
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint get_file_hash(HashAlgorithm algorithm, const char *path,
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                  char *output_string, size_t max_output_string) {
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA1_CTX context;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat sb;
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned char md[SHA1_DIGEST_LENGTH];
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int used;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t n;
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (algorithm != SHA_1) {
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = EINVAL;
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (stat(path, &sb) != 0) {
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (S_ISLNK(sb.st_mode)) {
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char buf[PATH_MAX];
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int len;
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = readlink(path, buf, sizeof(buf));
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (len < 0) {
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA1Init(&context);
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA1Update(&context, (unsigned char *) buf, len);
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA1Final(md, &context);
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (S_ISREG(sb.st_mode)) {
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char buf[10000];
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FILE *f = fopen(path, "rb");
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int len;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (f == NULL) {
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA1Init(&context);
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SHA1Update(&context, (unsigned char *) buf, len);
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ferror(f)) {
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fclose(f);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fclose(f);
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA1Final(md, &context);
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (S_ISLNK(sb.st_mode) || S_ISREG(sb.st_mode)) {
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        used = b64_ntop(md, SHA1_DIGEST_LENGTH,
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        output_string, max_output_string);
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (used < 0) {
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            errno = ENOSPC;
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        n = snprintf(output_string + used, max_output_string - used,
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                     " %d 0%o %d %d", (int) sb.st_size, sb.st_mode,
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                     (int) sb.st_uid, (int) sb.st_gid);
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        n = snprintf(output_string, max_output_string,
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                     "- - 0%o %d %d", sb.st_mode,
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                     (int) sb.st_uid, (int) sb.st_gid);
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (n >= max_output_string - used) {
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = ENOSPC;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -(used + n);
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return used + n;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct list {
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *name;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *next;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int cmp(const void *a, const void *b) {
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *const *ra = a;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *const *rb = b;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return strcmp((*ra)->name, (*rb)->name);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int recurse(HashAlgorithm algorithm, const char *directory_path,
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    struct list **out) {
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *list = NULL;
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *f;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent *de;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DIR *d = opendir(directory_path);
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (d == NULL) {
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while ((de = readdir(d)) != NULL) {
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (strcmp(de->d_name, ".") == 0) {
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (strcmp(de->d_name, "..") == 0) {
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *name = malloc(strlen(de->d_name) + 1);
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct list *node = malloc(sizeof(struct list));
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (name == NULL || node == NULL) {
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct list *next;
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (f = list; f != NULL; f = next) {
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                next = f->next;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f->name);
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f);
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(name);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(node);
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcpy(name, de->d_name);
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        node->name = name;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        node->next = list;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        list = node;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    closedir(d);
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (f = list; f != NULL; f = f->next) {
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct stat sb;
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *name;
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char outstr[NAME_MAX + 100];
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *keep;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct list *res;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name = malloc(strlen(f->name) + strlen(directory_path) + 2);
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (name == NULL) {
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct list *next;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (f = list; f != NULL; f = f->next) {
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                next = f->next;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f->name);
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f);
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (f = *out; f != NULL; f = f->next) {
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                next = f->next;
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f->name);
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f);
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *out = NULL;
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(name, "%s/%s", directory_path, f->name);
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int len = get_file_hash(algorithm, name,
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                outstr, sizeof(outstr));
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (len < 0) {
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // should not happen
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        keep = malloc(len + strlen(name) + 3);
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        res = malloc(sizeof(struct list));
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (keep == NULL || res == NULL) {
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct list *next;
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (f = list; f != NULL; f = f->next) {
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                next = f->next;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f->name);
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f);
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (f = *out; f != NULL; f = f->next) {
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                next = f->next;
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f->name);
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(f);
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *out = NULL;
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(keep);
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(res);
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(keep, "%s %s\n", name, outstr);
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        res->name = keep;
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        res->next = *out;
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *out = res;
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((stat(name, &sb) == 0) && S_ISDIR(sb.st_mode)) {
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (recurse(algorithm, name, out) < 0) {
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                struct list *next;
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                for (f = list; f != NULL; f = next) {
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    next = f->next;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    free(f->name);
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    free(f);
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return -1;
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *next;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (f = list; f != NULL; f = next) {
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        next = f->next;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(f->name);
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(f);
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/**
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Allocates a string containing the names and hashes of all files recursively
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * reached under the specified directory_path, using the specified algorithm.
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The string is returned as *output_string; the return value is the length
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * of the string, or a negative number if there was a failure.
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint get_recursive_hash_manifest(HashAlgorithm algorithm,
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                const char *directory_path,
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                char **output_string) {
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *out = NULL;
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *r;
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list **list;
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int count = 0;
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len = 0;
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int retlen = 0;
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *buf;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (recurse(algorithm, directory_path, &out) < 0) {
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (r = out; r != NULL; r = r->next) {
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        count++;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len += strlen(r->name);
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list = malloc(count * sizeof(struct list *));
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (list == NULL) {
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct list *next;
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (r = out; r != NULL; r = next) {
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            next = r->next;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(r->name);
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(r);
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    count = 0;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (r = out; r != NULL; r = r->next) {
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        list[count++] = r;
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    qsort(list, count, sizeof(struct list *), cmp);
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    buf = malloc(len + 1);
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (buf == NULL) {
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct list *next;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (r = out; r != NULL; r = next) {
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            next = r->next;
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(r->name);
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(r);
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(list);
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < count; i++) {
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int n = strlen(list[i]->name);
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcpy(buf + retlen, list[i]->name);
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        retlen += n;
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(list);
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct list *next;
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (r = out; r != NULL; r = next) {
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        next = r->next;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(r->name);
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(r);
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *output_string = buf;
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return retlen;
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
335