"Fossies" - the Fresh Open Source Software Archive 
Member "dosfstools-4.2/src/io.c" (31 Jan 2021, 4999 Bytes) of package /linux/misc/dosfstools-4.2.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "io.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
4.1_vs_4.2.
1 /* io.c - Virtual disk input/output
2
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>
7
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.
12
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.
17
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/>.
20
21 The complete text of the GNU General Public License
22 can be found in /usr/share/common-licenses/GPL-3 file.
23 */
24
25 /*
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.
29 */
30
31 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
32 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
33
34 #define _LARGEFILE64_SOURCE
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <errno.h>
42 #include <fcntl.h>
43
44 #include "fsck.fat.h"
45 #include "common.h"
46 #include "io.h"
47
48 typedef struct _change {
49 void *data;
50 off_t pos;
51 int size;
52 struct _change *next;
53 } CHANGE;
54
55 static CHANGE *changes, *last;
56 static int fd, did_change = 0;
57
58
59 void fs_open(const char *path, int rw)
60 {
61 if ((fd = open(path, rw ? O_RDWR : O_RDONLY)) < 0) {
62 perror("open");
63 exit(6);
64 }
65 changes = last = NULL;
66 did_change = 0;
67 }
68
69 /**
70 * Read data from the partition, accounting for any pending updates that are
71 * queued for writing.
72 *
73 * @param[in] pos Byte offset, relative to the beginning of the partition,
74 * at which to read
75 * @param[in] size Number of bytes to read
76 * @param[out] data Where to put the data read
77 */
78 void fs_read(off_t pos, int size, void *data)
79 {
80 CHANGE *walk;
81 int got;
82
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);
87 if (got != size)
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) {
91 if (walk->pos < pos)
92 memcpy(data, (char *)walk->data + pos - walk->pos,
93 min(size, walk->size - pos + walk->pos));
94 else
95 memcpy((char *)data + walk->pos - pos, walk->data,
96 min(walk->size, size + pos - walk->pos));
97 }
98 }
99 }
100
101 int fs_test(off_t pos, int size)
102 {
103 void *scratch;
104 int okay;
105
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;
110 free(scratch);
111 return okay;
112 }
113
114 void fs_write(off_t pos, int size, void *data)
115 {
116 CHANGE *new;
117 int did;
118
119 if (write_immed) {
120 did_change = 1;
121 if (lseek(fd, pos, 0) != pos)
122 pdie("Seek to %lld", (long long)pos);
123 if ((did = write(fd, data, size)) == size)
124 return;
125 if (did < 0)
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);
128 }
129 new = alloc(sizeof(CHANGE));
130 new->pos = pos;
131 memcpy(new->data = alloc(new->size = size), data, size);
132 new->next = NULL;
133 if (last)
134 last->next = new;
135 else
136 changes = new;
137 last = new;
138 }
139
140 static void fs_flush(void)
141 {
142 CHANGE *this;
143 int size;
144
145 while (changes) {
146 this = changes;
147 changes = changes->next;
148 if (lseek(fd, this->pos, 0) != this->pos)
149 fprintf(stderr,
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);
158 free(this->data);
159 free(this);
160 }
161 }
162
163 int fs_close(int write)
164 {
165 CHANGE *next;
166 int changed;
167
168 changed = ! !changes;
169 if (write)
170 fs_flush();
171 else
172 while (changes) {
173 next = changes->next;
174 free(changes->data);
175 free(changes);
176 changes = next;
177 }
178 if (close(fd) < 0)
179 pdie("closing filesystem");
180 return changed || did_change;
181 }
182
183 int fs_changed(void)
184 {
185 return ! !changes || did_change;
186 }