• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "hcs_file.h"
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <limits.h>
14 #include <unistd.h>
15 #include <securec.h>
16 #include "hcs_parser.h"
17 #include "hcs_mem.h"
18 #include "hcs_log.h"
19 
20 static char *g_outputFileName = NULL;
21 static FILE *g_outputFile = NULL;
22 static const char *g_inputFileName = NULL;
23 static bool g_dummyOutput = false;
24 static uint32_t g_outputWriteCount = 0;
25 static struct HcsFileQueue g_inputSourceFileQueue = { 0 };
26 static struct HcsSourceName *g_sourceNameSetHead = NULL;
27 
HcsSetInputFileName(const char * name)28 void HcsSetInputFileName(const char *name)
29 {
30     g_inputFileName = name;
31 }
32 
HcsGetInputFileName(void)33 const char *HcsGetInputFileName(void)
34 {
35     return g_inputFileName;
36 }
37 
HcsSourceNameSetPush(const char * name)38 int32_t HcsSourceNameSetPush(const char *name)
39 {
40     if (g_sourceNameSetHead == NULL) {
41         struct HcsSourceName *head = HcsMemZalloc(sizeof(*head));
42         if (head == NULL) {
43             HCS_ERROR("%s:%d OOM", __func__, __LINE__);
44             return EOOM;
45         }
46         head->name = name;
47         g_sourceNameSetHead = head;
48         return NOERR;
49     }
50 
51     struct HcsSourceName *pre = g_sourceNameSetHead;
52     struct HcsSourceName *last = pre;
53     while (last != NULL) {
54         if (!strcmp(last->name, name)) {
55             return EREOPENF;
56         }
57         pre = last;
58         last = last->next;
59     }
60 
61     struct HcsSourceName *newName = HcsMemZalloc(sizeof(struct HcsSourceName));
62     if (newName == NULL) {
63         HCS_ERROR("%s:%d OOM", __func__, __LINE__);
64         return EOOM;
65     }
66     newName->name = name;
67     pre->next = newName;
68     return NOERR;
69 }
70 
HcsSourceNameSetFind(const char * name)71 bool HcsSourceNameSetFind(const char *name)
72 {
73     struct HcsSourceName *last = g_sourceNameSetHead;
74 
75     while (last != NULL) {
76         if (!strcmp(last->name, name)) {
77             return true;
78         }
79         last = last->next;
80     }
81 
82     return false;
83 }
84 
HcsSourceNameSetClean(void)85 void HcsSourceNameSetClean(void)
86 {
87     struct HcsSourceName *term = g_sourceNameSetHead;
88 
89     while (term != NULL) {
90         struct HcsSourceName *temp = term->next;
91         HcsMemFree((void *)term->name);
92         HcsMemFree(term);
93         term = temp;
94     }
95 
96     g_sourceNameSetHead = NULL;
97 }
98 
GetFileName(const char * path)99 static const char *GetFileName(const char *path)
100 {
101     if (path == NULL) {
102         return NULL;
103     }
104     int32_t length = (int32_t)strlen(path);
105     int32_t i = length - 1;
106     for (; i >= 0; --i) {
107         if (path[i] == OS_SEPARATOR) {
108             break;
109         }
110     }
111 
112     return i >= 0 ? path + i + 1 : path;
113 }
114 
CopyFileName(const char * path)115 static const char *CopyFileName(const char *path)
116 {
117     return strdup(GetFileName(path));
118 }
119 
GetFileNameWithoutSuffix(const char * path)120 static const char *GetFileNameWithoutSuffix(const char *path)
121 {
122     char *fileNameRet = strdup(path);
123     if (fileNameRet == NULL) {
124         HCS_ERROR("oom");
125         return NULL;
126     }
127     char *it = fileNameRet + strlen(fileNameRet);
128     while (it != fileNameRet) {
129         if (*it == '.') {
130             *it = '\0';
131             break;
132         }
133         if (*it == OS_SEPARATOR) {
134             break;
135         }
136         it--;
137     }
138 
139     return fileNameRet;
140 }
141 
CopyAndSaveFileName(const char * filePath,char ** savedFileName,char ** savedFilePath)142 static int32_t CopyAndSaveFileName(const char *filePath, char **savedFileName, char **savedFilePath)
143 {
144     const char *fileName = CopyFileName(filePath);
145     if (fileName == NULL) {
146         return EOOM;
147     }
148 
149     /* if no specified output file name, use input name */
150     if (HcsGetOutPutFilePath() == NULL && HcsSetOutPutNameWithCurrentWorkPath(fileName)) {
151         HcsMemFree((void *)fileName);
152         return EOOM;
153     }
154 
155     char *path = strdup(filePath);
156     if (path == NULL || HcsSourceNameSetPush(path)) {
157         HcsMemFree((void *)fileName);
158         HcsMemFree((void *)path);
159         return EOOM;
160     }
161     *savedFileName = (char *)fileName;
162     *savedFilePath = path;
163     return NOERR;
164 }
165 
HcsOpenSourceFile(const char * path,struct HcsFile ** file,const char * flag)166 int32_t HcsOpenSourceFile(const char *path, struct HcsFile **file, const char *flag)
167 {
168     char pathBuf[PATH_MAX] = {'\0'};
169 #ifdef MINGW32
170     char *realPath = _fullpath(pathBuf, path, PATH_MAX);
171 #else
172     char *realPath = realpath(path, pathBuf);
173 #endif
174     if (realPath == NULL) {
175         HCS_ERROR("failed to open source file: %s", path);
176         return EINVALF;
177     }
178 
179     /* push to name set and check reopen */
180     if (HcsSourceNameSetFind(realPath)) {
181         return EREOPENF;
182     }
183 
184     HCS_DEBUG("source file path: %s", realPath);
185     FILE *f = fopen(realPath, flag ? flag : "r");
186     if (f == NULL) {
187         HCS_ERROR("failed to open source file: %s", realPath);
188         return EINVALF;
189     }
190 
191     char *fileName = NULL;
192     char *filePath = NULL;
193     int32_t ret = CopyAndSaveFileName(realPath, &fileName, &filePath);
194     if (ret) {
195         fclose(f);
196         return EFAIL;
197     }
198 
199     struct HcsFile *sourceFile = HcsMemZalloc(sizeof(struct HcsFile));
200     if (sourceFile == NULL) {
201         HcsMemFree(fileName);
202         HcsMemFree(filePath);
203         fclose(f);
204         HCS_ERROR("oom");
205         return EOOM;
206     }
207     sourceFile->name = fileName;
208     sourceFile->fullPath = filePath;
209     sourceFile->file = f;
210     sourceFile->pos = 0;
211     *file = sourceFile;
212     return NOERR;
213 }
214 
HcsSourceFileGetSize(struct HcsFile * file)215 uint64_t HcsSourceFileGetSize(struct HcsFile *file)
216 {
217     uint64_t currentPos = ftell(file->file);
218 
219     fseek(file->file, 0, SEEK_END);
220     uint64_t fileSize = ftell(file->file);
221     fseek(file->file, currentPos, SEEK_SET);
222 
223     return fileSize;
224 }
225 
HcsSourceFileRead(struct HcsFile * file,uint8_t * out,uint32_t readSize)226 int32_t HcsSourceFileRead(struct HcsFile *file, uint8_t *out, uint32_t readSize)
227 {
228     struct HcsFile *currentSrc = file ? file : HcsSourceQueueTop();
229     if (currentSrc == NULL) {
230         HCS_ERROR("source file not valid");
231         return -EINVALF;
232     }
233 
234     return fread(out, 1, readSize, currentSrc->file);
235 }
236 
HcsGetSourceFilePos(struct HcsFile * file)237 uint32_t HcsGetSourceFilePos(struct HcsFile *file)
238 {
239     struct HcsFile *currentSrc = file ? file : HcsSourceQueueTop();
240     return ftell(currentSrc->file);
241 }
242 
HcsCloseFile(struct HcsFile * file)243 void HcsCloseFile(struct HcsFile *file)
244 {
245     if (file == NULL) {
246         return;
247     }
248 
249     fclose(file->file);
250     HcsMemFree((void *)file->name);
251     HcsMemFree(file);
252 }
253 
HcsSetOutPutNameWithCurrentWorkPath(const char * name)254 int32_t HcsSetOutPutNameWithCurrentWorkPath(const char *name)
255 {
256     char outPutPath[PATH_MAX] = {0};
257     char *cwd = getcwd(outPutPath, PATH_MAX);
258     if (cwd == NULL || !strlen(cwd)) {
259         return EFAIL;
260     }
261 
262     if (sprintf_s(outPutPath + strlen(outPutPath), PATH_MAX - strlen(outPutPath), "%c", OS_SEPARATOR) < 0) {
263         return EFAIL;
264     }
265 
266     if (strcat_s(outPutPath, PATH_MAX, name) != EOK) {
267         return EFAIL;
268     }
269 
270     return HcsSetOutPutName(outPutPath);
271 }
272 
HcsSetOutPutName(const char * name)273 int32_t HcsSetOutPutName(const char *name)
274 {
275     if (g_outputFileName != NULL) {
276         HcsMemFree(g_outputFileName);
277     }
278 
279     g_outputFileName = strdup(name);
280     if (g_outputFileName == NULL) {
281         HCS_ERROR("oom");
282         return EOOM;
283     }
284 #ifdef OS_WIN
285     char *temp = g_outputFileName;
286     while (*temp != '\0') {
287         if (*temp == UNIX_SEPARATOR) {
288             *temp = WIN_SEPARATOR;
289         }
290         temp++;
291     }
292 #endif
293 
294     return NOERR;
295 }
296 
HcsSetOutputFileSuffix(const char * suffix)297 bool HcsSetOutputFileSuffix(const char *suffix)
298 {
299     const char *fileNameBefore = g_outputFileName;
300     const char *fileNameWithoutSuffix = GetFileNameWithoutSuffix(fileNameBefore);
301     if (fileNameWithoutSuffix == NULL) {
302         return false;
303     }
304 
305     uint32_t newNameSize = strlen(g_outputFileName) + strlen(suffix) + 1;
306     char *newOutputFilename = HcsMemZalloc(newNameSize);
307     if (newOutputFilename == NULL) {
308         HcsMemFree((void *)fileNameWithoutSuffix);
309         return false;
310     }
311 
312     int32_t ret = strcpy_s(newOutputFilename, newNameSize, fileNameWithoutSuffix);
313     HcsMemFree((void *)fileNameWithoutSuffix);
314     if (ret) {
315         HCS_ERROR("failed to copy string");
316         HcsMemFree(newOutputFilename);
317         return false;
318     }
319     ret = strcat_s(newOutputFilename, newNameSize, suffix);
320     if (ret) {
321         HCS_ERROR("failed to copy string");
322         HcsMemFree(newOutputFilename);
323         return false;
324     }
325 
326     HcsMemFree((void *)fileNameBefore);
327     g_outputFileName = newOutputFilename;
328     return true;
329 }
330 
331 // return output file name only
HcsGetOutputFileName(void)332 const char *HcsGetOutputFileName(void)
333 {
334     return GetFileName(g_outputFileName);
335 }
336 
HcsGetOutputFileNameWithoutSuffix(void)337 char *HcsGetOutputFileNameWithoutSuffix(void)
338 {
339     const char *fileName = HcsGetOutputFileName();
340     if (fileName == NULL) {
341         return NULL;
342     }
343 
344     char *retName = strdup(fileName);
345     if (retName == NULL) {
346         HCS_ERROR("oom");
347         return NULL;
348     }
349 
350     char *dot = strchr(retName, '.');
351     if (dot != NULL) {
352         *dot = '\0';
353     }
354     return retName;
355 }
356 
357 
358 // return full path of output file
HcsGetOutPutFilePath(void)359 const char *HcsGetOutPutFilePath(void)
360 {
361     return g_outputFileName;
362 }
363 
HcsOutputNameVerify()364 bool HcsOutputNameVerify()
365 {
366     const char *fileName = g_outputFileName;
367     char lastChar = fileName[strlen(fileName) - 1];
368     if (lastChar == OS_SEPARATOR) {
369         HCS_ERROR("output name is DIR");
370         return false;
371     }
372 
373     return true;
374 }
375 
HcsOpenOutputFile(const char * suffix)376 struct HcsFile *HcsOpenOutputFile(const char *suffix)
377 {
378     if (!HcsOutputNameVerify()) {
379         return NULL;
380     }
381     if (!HcsSetOutputFileSuffix(suffix)) {
382         return NULL;
383     }
384     const char *outputFileName = HcsGetOutPutFilePath();
385     g_outputFile = fopen(outputFileName, "wb");
386     if (g_outputFile == NULL) {
387         HCS_ERROR("failed to open output file: %s", outputFileName);
388         return NULL;
389     }
390 
391     HCS_DEBUG("Output: %s", outputFileName);
392     struct HcsFile *outputFile = HcsMemZalloc(sizeof(struct HcsFile));
393     if (outputFile == NULL) {
394         HCS_ERROR("oom");
395         fclose(g_outputFile);
396         g_outputFile = NULL;
397         return NULL;
398     }
399     outputFile->name = outputFileName;
400     outputFile->file = g_outputFile;
401     outputFile->pos = 0;
402     outputFile->fullPath = outputFileName;
403     g_outputWriteCount = 0;
404 
405     return outputFile;
406 }
407 
HcsCloseOutput(struct HcsFile * output)408 void HcsCloseOutput(struct HcsFile *output)
409 {
410     if (output == NULL || output->file == NULL) {
411         return;
412     }
413 
414     fflush(output->file);
415     fclose(output->file);
416 
417     HcsMemFree(output);
418     g_outputWriteCount = 0;
419 }
420 
HcsOutputWrite(const void * buffer,uint32_t length)421 int32_t HcsOutputWrite(const void *buffer, uint32_t length)
422 {
423     g_outputWriteCount += length;
424     if (g_dummyOutput || !length) {
425         return NOERR;
426     }
427 
428     uint32_t writeLen = fwrite(buffer, 1, length, g_outputFile);
429     if (writeLen != length) {
430         HCS_ERROR("failed to write output file");
431         return EOUTPUT;
432     }
433 
434     return NOERR;
435 }
436 
437 #define WRITE_MAX_PER_TIME 2048
438 
HcsFormatOutputWrite(const char * format,...)439 int32_t HcsFormatOutputWrite(const char *format, ...)
440 {
441     if (format == NULL) {
442         return EINVALARG;
443     }
444     static char writeBuffer[WRITE_MAX_PER_TIME] = {'\0'};
445 
446     va_list argList;
447 
448     va_start(argList, format);
449     int length = vsprintf_s(writeBuffer, WRITE_MAX_PER_TIME, format, argList);
450     va_end(argList);
451 
452     if (length < 0) {
453         HCS_ERROR("Output too long in one time");
454         return EOUTPUT;
455     }
456     return HcsOutputWrite(writeBuffer, length);
457 }
458 
HcsOutputWriteAlign(const void * buffer,uint32_t length)459 int32_t HcsOutputWriteAlign(const void *buffer, uint32_t length)
460 {
461     static const uint8_t alignData[ALIGN_SIZE]  = {0};
462     int32_t ret = HcsOutputWrite(buffer, length);
463     if (ret) {
464         return ret;
465     }
466     int32_t appendSize = HcsAlign(length) - length;
467     if (appendSize) {
468         ret = HcsOutputWrite(alignData, appendSize);
469     }
470     return ret;
471 }
472 
HcsMockOutPut(bool dummyOutput)473 void HcsMockOutPut(bool dummyOutput)
474 {
475     g_dummyOutput = dummyOutput;
476 }
477 
HcsGetOutputCurrentCount(void)478 uint32_t HcsGetOutputCurrentCount(void)
479 {
480     return g_outputWriteCount;
481 }
482 
HcsResetOutputCurrentCount(void)483 void HcsResetOutputCurrentCount(void)
484 {
485     g_outputWriteCount = 0;
486 }
487 
HcsSourceQueuePush(struct HcsFile * sourceFile)488 void HcsSourceQueuePush(struct HcsFile *sourceFile)
489 {
490     struct HcsFileQueue *sourceQueue = &g_inputSourceFileQueue;
491     struct HcsFile *queueLast = sourceQueue->head;
492     if (queueLast == NULL) {
493         sourceQueue->head = sourceFile;
494         sourceQueue->count = 1;
495         return;
496     }
497 
498     while (queueLast->next) {
499         queueLast = queueLast->next;
500     }
501 
502     queueLast->next = sourceFile;
503     sourceQueue->count++;
504 }
505 
HcsSourceQueuePop(void)506 void HcsSourceQueuePop(void)
507 {
508     struct HcsFileQueue *sourceQueue = &g_inputSourceFileQueue;
509     if (sourceQueue->head == NULL) {
510         return;
511     }
512     sourceQueue->head = sourceQueue->head->next;
513     sourceQueue->count--;
514 }
515 
HcsSourceQueueTop(void)516 struct HcsFile *HcsSourceQueueTop(void)
517 {
518     return g_inputSourceFileQueue.head;
519 }
520 
HcsSourceQueueSize(void)521 uint32_t HcsSourceQueueSize(void)
522 {
523     return g_inputSourceFileQueue.count;
524 }
525 
HcsGetCurrentSourceName(void)526 const char *HcsGetCurrentSourceName(void)
527 {
528     struct HcsFile *source = HcsSourceQueueTop();
529     return source ? source->fullPath : "";
530 }
531 
HcsFileCopyDir(char * dst,uint32_t dstBufferSize,const char * fullPath)532 bool HcsFileCopyDir(char *dst, uint32_t dstBufferSize, const char *fullPath)
533 {
534     const char *c = strrchr(fullPath, OS_SEPARATOR);
535     if (c == NULL) {
536         HCS_ERROR("%s: path '%s' not include dir", __func__, fullPath);
537         return false;
538     }
539     int32_t len = (int32_t)(c - fullPath) + 1;
540     int32_t ret = strncpy_s(dst, dstBufferSize, fullPath, len);
541     if (ret) {
542         HCS_ERROR("%s:string copy fail", __func__);
543         return false;
544     }
545     dst[len] = '\0';
546 
547     return true;
548 }