• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Android Open Source Project
2 //
3 // This software is licensed under the terms of the GNU General Public
4 // License version 2, as published by the Free Software Foundation, and
5 // may be copied, distributed, and modified under those terms.
6 //
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License for more details.
11 
12 #include "android/utils/file_data.h"
13 
14 #include "android/utils/panic.h"
15 
16 #include <errno.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 // Use a magic value in the |flags| field to indicate that a FileData
22 // value was properly initialized. Helps catch errors at runtime.
23 #define FILE_DATA_MAGIC   ((size_t)0x87002013U)
24 
25 
fileData_isValid(const FileData * data)26 bool fileData_isValid(const FileData* data) {
27     if (!data)
28         return false;
29     if (data->flags == FILE_DATA_MAGIC)
30         return true;
31     if (data->flags == 0 && data->data == NULL && data->size == 0)
32         return true;
33     return false;
34 }
35 
fileData_setValid(FileData * data)36 static inline void fileData_setValid(FileData* data) {
37     data->flags = FILE_DATA_MAGIC;
38 }
39 
40 
fileData_setInvalid(FileData * data)41 static inline void fileData_setInvalid(FileData* data) {
42     data->flags = (size_t)0xDEADBEEFU;
43 }
44 
45 
fileData_initWith(FileData * data,const void * buff,size_t size)46 static void fileData_initWith(FileData* data,
47                               const void* buff,
48                               size_t size) {
49     data->data = size ? (uint8_t*)buff : NULL;
50     data->size = size;
51     fileData_setValid(data);
52 }
53 
54 
fileData_initEmpty(FileData * data)55 void fileData_initEmpty(FileData* data) {
56     fileData_initWith(data, NULL, 0);
57 }
58 
59 
fileData_initFromFile(FileData * data,const char * filePath)60 int fileData_initFromFile(FileData* data, const char* filePath) {
61     FILE* f = fopen(filePath, "rb");
62     if (!f)
63         return -errno;
64 
65     int ret = 0;
66     do {
67         if (fseek(f, 0, SEEK_END) < 0) {
68             ret = -errno;
69             break;
70         }
71 
72         long fileSize = ftell(f);
73         if (fileSize < 0) {
74             ret = -errno;
75             break;
76         }
77 
78         if (fileSize == 0) {
79             fileData_initEmpty(data);
80             break;
81         }
82 
83         if (fseek(f, 0, SEEK_SET) < 0) {
84             ret = -errno;
85             break;
86         }
87 
88         char* buffer = malloc((size_t)fileSize);
89         if (!buffer) {
90             ret = -errno;
91             break;
92         }
93 
94         size_t readLen = fread(buffer, 1, (size_t)fileSize, f);
95         if (readLen != (size_t)fileSize) {
96             if (feof(f)) {
97                 ret = -EIO;
98             } else {
99                 ret = -ferror(f);
100             }
101             break;
102         }
103 
104         fileData_initWith(data, buffer, readLen);
105 
106     } while (0);
107 
108     fclose(f);
109     return ret;
110 }
111 
112 
fileData_initFrom(FileData * data,const FileData * other)113 int fileData_initFrom(FileData* data, const FileData* other) {
114     if (!other || !fileData_isValid(other)) {
115         APANIC("Trying to copy an uninitialized FileData instance\n");
116     }
117     if (other->size == 0) {
118         fileData_initEmpty(data);
119         return 0;
120     }
121     void* copy = malloc(other->size);
122     if (!copy) {
123         return -errno;
124     }
125 
126     memcpy(copy, other->data, other->size);
127     fileData_initWith(data, copy, other->size);
128     return 0;
129 }
130 
131 
fileData_initFromMemory(FileData * data,const void * input,size_t inputLen)132 int fileData_initFromMemory(FileData* data,
133                              const void* input,
134                              size_t inputLen) {
135     FileData other;
136     fileData_initWith(&other, input, inputLen);
137     memset(data, 0, sizeof(*data));  // make valgrind happy.
138     return fileData_initFrom(data, &other);
139 }
140 
141 
fileData_swap(FileData * data,FileData * other)142 void fileData_swap(FileData* data, FileData* other) {
143     if (!fileData_isValid(data) || !fileData_isValid(data))
144         APANIC("Trying to swap un-initialized FileData instance\n");
145 
146     uint8_t* buffer = data->data;
147     data->data = other->data;
148     other->data = buffer;
149 
150     size_t size = data->size;
151     data->size = other->size;
152     other->size = size;
153 }
154 
155 
fileData_done(FileData * data)156 void fileData_done(FileData* data) {
157     if (!fileData_isValid(data)) {
158         APANIC("Trying to finalize an un-initialized FileData instance\n");
159     }
160 
161     free(data->data);
162     fileData_initWith(data, NULL, 0);
163     fileData_setInvalid(data);
164 }
165