Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f2944aa authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "Remove dead code."

parents 6a2d5a34 d5ff3e94
Loading
Loading
Loading
Loading

include/cutils/dir_hash.h

deleted100644 → 0
+0 −26
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

typedef enum {
    SHA_1,
} HashAlgorithm;

int get_file_hash(HashAlgorithm algorithm, const char *path,
                  char *output_string, size_t max_output_string);

int get_recursive_hash_manifest(HashAlgorithm algorithm,
                                const char *directory_path,
                                char **output_string);

libcutils/dir_hash.c

deleted100644 → 0
+0 −335
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sha1.h>
#include <unistd.h>
#include <limits.h>

#include <sys/stat.h>

#include <netinet/in.h>
#include <resolv.h>

#include <cutils/dir_hash.h>

/**
 * Copies, if it fits within max_output_string bytes, into output_string
 * a hash of the contents, size, permissions, uid, and gid of the file
 * specified by path, using the specified algorithm.  Returns the length
 * of the output string, or a negative number if the buffer is too short.
 */
int get_file_hash(HashAlgorithm algorithm, const char *path,
                  char *output_string, size_t max_output_string) {
    SHA1_CTX context;
    struct stat sb;
    unsigned char md[SHA1_DIGEST_LENGTH];
    int used;
    size_t n;

    if (algorithm != SHA_1) {
        errno = EINVAL;
        return -1;
    }

    if (stat(path, &sb) != 0) {
        return -1;
    }

    if (S_ISLNK(sb.st_mode)) {
        char buf[PATH_MAX];
        int len;

        len = readlink(path, buf, sizeof(buf));
        if (len < 0) {
            return -1;
        }

        SHA1Init(&context);
        SHA1Update(&context, (unsigned char *) buf, len);
        SHA1Final(md, &context);
    } else if (S_ISREG(sb.st_mode)) {
        char buf[10000];
        FILE *f = fopen(path, "rb");
        int len;

        if (f == NULL) {
            return -1;
        }

        SHA1Init(&context);

        while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
            SHA1Update(&context, (unsigned char *) buf, len);
        }

        if (ferror(f)) {
            fclose(f);
            return -1;
        }

        fclose(f);
        SHA1Final(md, &context);
    }

    if (S_ISLNK(sb.st_mode) || S_ISREG(sb.st_mode)) {
        used = b64_ntop(md, SHA1_DIGEST_LENGTH,
                        output_string, max_output_string);
        if (used < 0) {
            errno = ENOSPC;
            return -1;
        }

        n = snprintf(output_string + used, max_output_string - used,
                     " %d 0%o %d %d", (int) sb.st_size, sb.st_mode,
                     (int) sb.st_uid, (int) sb.st_gid);
    } else {
        n = snprintf(output_string, max_output_string,
                     "- - 0%o %d %d", sb.st_mode,
                     (int) sb.st_uid, (int) sb.st_gid);
    }

    if (n >= max_output_string - used) {
        errno = ENOSPC;
        return -(used + n);
    }

    return used + n;
}

struct list {
    char *name;
    struct list *next;
};

static int cmp(const void *a, const void *b) {
    struct list *const *ra = a;
    struct list *const *rb = b;

    return strcmp((*ra)->name, (*rb)->name);
}

static int recurse(HashAlgorithm algorithm, const char *directory_path,
                    struct list **out) {
    struct list *list = NULL;
    struct list *f;

    struct dirent *de;
    DIR *d = opendir(directory_path);

    if (d == NULL) {
        return -1;
    }

    while ((de = readdir(d)) != NULL) {
        if (strcmp(de->d_name, ".") == 0) {
            continue;
        }
        if (strcmp(de->d_name, "..") == 0) {
            continue;
        }

        char *name = malloc(strlen(de->d_name) + 1);
        struct list *node = malloc(sizeof(struct list));

        if (name == NULL || node == NULL) {
            struct list *next;
            for (f = list; f != NULL; f = next) {
                next = f->next;
                free(f->name);
                free(f);
            }

            free(name);
            free(node);
            closedir(d);
            return -1;
        }

        strcpy(name, de->d_name);

        node->name = name;
        node->next = list;
        list = node;
    }

    closedir(d);

    for (f = list; f != NULL; f = f->next) {
        struct stat sb;
        char *name;
        char outstr[NAME_MAX + 100];
        char *keep;
        struct list *res;

        name = malloc(strlen(f->name) + strlen(directory_path) + 2);
        if (name == NULL) {
            struct list *next;
            for (f = list; f != NULL; f = f->next) {
                next = f->next;
                free(f->name);
                free(f);
            }
            for (f = *out; f != NULL; f = f->next) {
                next = f->next;
                free(f->name);
                free(f);
            }
            *out = NULL;
            return -1;
        }

        sprintf(name, "%s/%s", directory_path, f->name);

        int len = get_file_hash(algorithm, name,
                                outstr, sizeof(outstr));
        if (len < 0) {
            // should not happen
            return -1;
        }

        keep = malloc(len + strlen(name) + 3);
        res = malloc(sizeof(struct list));

        if (keep == NULL || res == NULL) {
            struct list *next;
            for (f = list; f != NULL; f = f->next) {
                next = f->next;
                free(f->name);
                free(f);
            }
            for (f = *out; f != NULL; f = f->next) {
                next = f->next;
                free(f->name);
                free(f);
            }
            *out = NULL;

            free(keep);
            free(res);
            return -1;
        }

        sprintf(keep, "%s %s\n", name, outstr);

        res->name = keep;
        res->next = *out;
        *out = res;

        if ((stat(name, &sb) == 0) && S_ISDIR(sb.st_mode)) {
            if (recurse(algorithm, name, out) < 0) {
                struct list *next;
                for (f = list; f != NULL; f = next) {
                    next = f->next;
                    free(f->name);
                    free(f);
                }

                return -1;
            }
        }
    }

    struct list *next;
    for (f = list; f != NULL; f = next) {
        next = f->next;

        free(f->name);
        free(f);
    }
}

/**
 * Allocates a string containing the names and hashes of all files recursively
 * reached under the specified directory_path, using the specified algorithm.
 * The string is returned as *output_string; the return value is the length
 * of the string, or a negative number if there was a failure.
 */
int get_recursive_hash_manifest(HashAlgorithm algorithm,
                                const char *directory_path,
                                char **output_string) {
    struct list *out = NULL;
    struct list *r;
    struct list **list;
    int count = 0;
    int len = 0;
    int retlen = 0;
    int i;
    char *buf;
    
    if (recurse(algorithm, directory_path, &out) < 0) {
        return -1;
    }

    for (r = out; r != NULL; r = r->next) {
        count++;
        len += strlen(r->name);
    }

    list = malloc(count * sizeof(struct list *));
    if (list == NULL) {
        struct list *next;
        for (r = out; r != NULL; r = next) {
            next = r->next;
            free(r->name);
            free(r);
        }
        return -1;
    }

    count = 0;
    for (r = out; r != NULL; r = r->next) {
        list[count++] = r;
    }

    qsort(list, count, sizeof(struct list *), cmp);

    buf = malloc(len + 1);
    if (buf == NULL) {
        struct list *next;
        for (r = out; r != NULL; r = next) {
            next = r->next;
            free(r->name);
            free(r);
        }
        free(list);
        return -1;
    }

    for (i = 0; i < count; i++) {
        int n = strlen(list[i]->name);

        strcpy(buf + retlen, list[i]->name);
        retlen += n;
    }

    free(list);

    struct list *next;
    for (r = out; r != NULL; r = next) {
        next = r->next;

        free(r->name);
        free(r);
    }

    *output_string = buf;
    return retlen;
}