1 /* io.c - Virtual disk input/output
3 Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
4 Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5 Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
6 Copyright (C) 2015 Andreas Bombe <aeb@debian.org>
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 The complete text of the GNU General Public License
22 can be found in /usr/share/common-licenses/GPL-3 file.
26 * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>
27 * Fixed nasty bug that caused every file with a name like
28 * xxxxxxxx.xxx to be treated as bad name that needed to be fixed.
31 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
32 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
34 #define _LARGEFILE64_SOURCE
39 #include <sys/types.h>
48 typedef struct _change {
55 static CHANGE *changes, *last;
56 static int fd, did_change = 0;
59 void fs_open(char *path, int rw)
61 if ((fd = open(path, rw ? O_RDWR : O_RDONLY)) < 0) {
65 changes = last = NULL;
70 * Read data from the partition, accounting for any pending updates that are
73 * @param[in] pos Byte offset, relative to the beginning of the partition,
75 * @param[in] size Number of bytes to read
76 * @param[out] data Where to put the data read
78 void fs_read(off_t pos, int size, void *data)
83 if (lseek(fd, pos, 0) != pos)
84 pdie("Seek to %lld", (long long)pos);
85 if ((got = read(fd, data, size)) < 0)
86 pdie("Read %d bytes at %lld", size, (long long)pos);
88 die("Got %d bytes instead of %d at %lld", got, size, (long long)pos);
89 for (walk = changes; walk; walk = walk->next) {
90 if (walk->pos < pos + size && walk->pos + walk->size > pos) {
92 memcpy(data, (char *)walk->data + pos - walk->pos,
93 min(size, walk->size - pos + walk->pos));
95 memcpy((char *)data + walk->pos - pos, walk->data,
96 min(walk->size, size + pos - walk->pos));
101 int fs_test(off_t pos, int size)
106 if (lseek(fd, pos, 0) != pos)
107 pdie("Seek to %lld", (long long)pos);
108 scratch = alloc(size);
109 okay = read(fd, scratch, size) == size;
114 void fs_write(off_t pos, int size, void *data)
121 if (lseek(fd, pos, 0) != pos)
122 pdie("Seek to %lld", (long long)pos);
123 if ((did = write(fd, data, size)) == size)
126 pdie("Write %d bytes at %lld", size, (long long)pos);
127 die("Wrote %d bytes instead of %d at %lld", did, size, (long long)pos);
129 new = alloc(sizeof(CHANGE));
131 memcpy(new->data = alloc(new->size = size), data, size);
140 static void fs_flush(void)
147 changes = changes->next;
148 if (lseek(fd, this->pos, 0) != this->pos)
150 "Seek to %lld failed: %s\n Did not write %d bytes.\n",
151 (long long)this->pos, strerror(errno), this->size);
152 else if ((size = write(fd, this->data, this->size)) < 0)
153 fprintf(stderr, "Writing %d bytes at %lld failed: %s\n", this->size,
154 (long long)this->pos, strerror(errno));
155 else if (size != this->size)
156 fprintf(stderr, "Wrote %d bytes instead of %d bytes at %lld."
157 "\n", size, this->size, (long long)this->pos);
163 int fs_close(int write)
168 changed = ! !changes;
173 next = changes->next;
179 pdie("closing filesystem");
180 return changed || did_change;
185 return ! !changes || did_change;