src/util/vfs/vfs-file.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "util/vfs.h"
7
8#include "util/memory.h"
9
10#include <stdio.h>
11
12struct VFileFILE {
13 struct VFile d;
14 FILE* file;
15};
16
17static bool _vffClose(struct VFile* vf);
18static off_t _vffSeek(struct VFile* vf, off_t offset, int whence);
19static ssize_t _vffRead(struct VFile* vf, void* buffer, size_t size);
20static ssize_t _vffWrite(struct VFile* vf, const void* buffer, size_t size);
21static void* _vffMap(struct VFile* vf, size_t size, int flags);
22static void _vffUnmap(struct VFile* vf, void* memory, size_t size);
23static void _vffTruncate(struct VFile* vf, size_t size);
24static ssize_t _vffSize(struct VFile* vf);
25
26struct VFile* VFileFOpen(const char* path, const char* mode) {
27 if (!path && !mode) {
28 return 0;
29 }
30 FILE* file = fopen(path, mode);
31 return VFileFromFILE(file);
32}
33
34struct VFile* VFileFromFILE(FILE* file) {
35 if (!file) {
36 return 0;
37 }
38
39 struct VFileFILE* vff = malloc(sizeof(struct VFileFILE));
40 if (!vff) {
41 return 0;
42 }
43
44 vff->file = file;
45 vff->d.close = _vffClose;
46 vff->d.seek = _vffSeek;
47 vff->d.read = _vffRead;
48 vff->d.readline = VFileReadline;
49 vff->d.write = _vffWrite;
50 vff->d.map = _vffMap;
51 vff->d.unmap = _vffUnmap;
52 vff->d.truncate = _vffTruncate;
53 vff->d.size = _vffSize;
54
55 return &vff->d;
56}
57
58bool _vffClose(struct VFile* vf) {
59 struct VFileFILE* vff = (struct VFileFILE*) vf;
60 if (fclose(vff->file) < 0) {
61 return false;
62 }
63 free(vff);
64 return true;
65}
66
67off_t _vffSeek(struct VFile* vf, off_t offset, int whence) {
68 struct VFileFILE* vff = (struct VFileFILE*) vf;
69 return fseek(vff->file, offset, whence);
70}
71
72ssize_t _vffRead(struct VFile* vf, void* buffer, size_t size) {
73 struct VFileFILE* vff = (struct VFileFILE*) vf;
74 return fread(buffer, size, 1, vff->file);
75}
76
77ssize_t _vffWrite(struct VFile* vf, const void* buffer, size_t size) {
78 struct VFileFILE* vff = (struct VFileFILE*) vf;
79 return fwrite(buffer, size, 1, vff->file);
80}
81
82static void* _vffMap(struct VFile* vf, size_t size, int flags) {
83 UNUSED(flags);
84 struct VFileFILE* vff = (struct VFileFILE*) vf;
85 void* mem = anonymousMemoryMap(size);
86 if (!mem) {
87 return 0;
88 }
89 long pos = ftell(vff->file);
90 fseek(vff->file, 0, SEEK_SET);
91 fread(mem, size, 1, vff->file);
92 fseek(vff->file, pos, SEEK_SET);
93 return mem;
94}
95
96static void _vffUnmap(struct VFile* vf, void* memory, size_t size) {
97 struct VFileFILE* vff = (struct VFileFILE*) vf;
98 long pos = ftell(vff->file);
99 fseek(vff->file, 0, SEEK_SET);
100 fwrite(memory, size, 1, vff->file);
101 fseek(vff->file, pos, SEEK_SET);
102 mappedMemoryFree(memory, size);
103}
104
105static void _vffTruncate(struct VFile* vf, size_t size) {
106 struct VFileFILE* vff = (struct VFileFILE*) vf;
107 long pos = ftell(vff->file);
108 fseek(vff->file, 0, SEEK_END);
109 ssize_t realSize = ftell(vff->file);
110 if (realSize < 0) {
111 return;
112 }
113 while (size > (size_t) realSize) {
114 static const char zeros[128] = "";
115 size_t diff = size - realSize;
116 if (diff > sizeof(zeros)) {
117 diff = sizeof(zeros);
118 }
119 fwrite(zeros, diff, 1, vff->file);
120 realSize += diff;
121 }
122 fseek(vff->file, pos, SEEK_SET);
123}
124
125static ssize_t _vffSize(struct VFile* vf) {
126 struct VFileFILE* vff = (struct VFileFILE*) vf;
127 long pos = ftell(vff->file);
128 fseek(vff->file, 0, SEEK_END);
129 ssize_t size = ftell(vff->file);
130 fseek(vff->file, pos, SEEK_SET);
131 return size;
132}