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