aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/cow_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers/cow_user.c')
-rw-r--r--arch/um/drivers/cow_user.c133
1 files changed, 65 insertions, 68 deletions
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 0ec4052db9c5..93f227a25ba4 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -1,17 +1,18 @@
1#include <stddef.h> 1/*
2#include <string.h> 2 * Copyright (C) 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
3#include <errno.h> 3 * Licensed under the GPL
4/* _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines 4 */
5
6/*
7 * _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines
5 * that. 8 * that.
6 */ 9 */
7#include <unistd.h> 10#include <unistd.h>
8#include <byteswap.h> 11#include <byteswap.h>
9#include <sys/time.h> 12#include <errno.h>
10#include <sys/param.h> 13#include <string.h>
11#include <sys/user.h> 14#include <arpa/inet.h>
12 15#include <asm/types.h>
13#include "os.h"
14
15#include "cow.h" 16#include "cow.h"
16#include "cow_sys.h" 17#include "cow_sys.h"
17 18
@@ -28,7 +29,8 @@ struct cow_header_v1 {
28 __s32 sectorsize; 29 __s32 sectorsize;
29} __attribute__((packed)); 30} __attribute__((packed));
30 31
31/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in 32/*
33 * Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
32 * case other systems have different values for MAXPATHLEN. 34 * case other systems have different values for MAXPATHLEN.
33 * 35 *
34 * The same must hold for V2 - we want file format compatibility, not anything 36 * The same must hold for V2 - we want file format compatibility, not anything
@@ -46,7 +48,8 @@ struct cow_header_v2 {
46 __s32 sectorsize; 48 __s32 sectorsize;
47} __attribute__((packed)); 49} __attribute__((packed));
48 50
49/* Changes from V2 - 51/*
52 * Changes from V2 -
50 * PATH_LEN_V3 as described above 53 * PATH_LEN_V3 as described above
51 * Explicitly specify field bit lengths for systems with different 54 * Explicitly specify field bit lengths for systems with different
52 * lengths for the usual C types. Not sure whether char or 55 * lengths for the usual C types. Not sure whether char or
@@ -70,7 +73,8 @@ struct cow_header_v2 {
70 * Fixed (finally!) the rounding bug 73 * Fixed (finally!) the rounding bug
71 */ 74 */
72 75
73/* Until Dec2005, __attribute__((packed)) was left out from the below 76/*
77 * Until Dec2005, __attribute__((packed)) was left out from the below
74 * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to 78 * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to
75 * align size to 8-byte alignment. This shifted all fields above (no padding 79 * align size to 8-byte alignment. This shifted all fields above (no padding
76 * was present on 32-bit, no other padding was added). 80 * was present on 32-bit, no other padding was added).
@@ -122,7 +126,7 @@ void cow_sizes(int version, __u64 size, int sectorsize, int align,
122 int bitmap_offset, unsigned long *bitmap_len_out, 126 int bitmap_offset, unsigned long *bitmap_len_out,
123 int *data_offset_out) 127 int *data_offset_out)
124{ 128{
125 if(version < 3){ 129 if (version < 3) {
126 *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); 130 *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
127 131
128 *data_offset_out = bitmap_offset + *bitmap_len_out; 132 *data_offset_out = bitmap_offset + *bitmap_len_out;
@@ -144,46 +148,46 @@ static int absolutize(char *to, int size, char *from)
144 char save_cwd[256], *slash; 148 char save_cwd[256], *slash;
145 int remaining; 149 int remaining;
146 150
147 if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { 151 if (getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
148 cow_printf("absolutize : unable to get cwd - errno = %d\n", 152 cow_printf("absolutize : unable to get cwd - errno = %d\n",
149 errno); 153 errno);
150 return(-1); 154 return -1;
151 } 155 }
152 slash = strrchr(from, '/'); 156 slash = strrchr(from, '/');
153 if(slash != NULL){ 157 if (slash != NULL) {
154 *slash = '\0'; 158 *slash = '\0';
155 if(chdir(from)){ 159 if (chdir(from)) {
156 *slash = '/'; 160 *slash = '/';
157 cow_printf("absolutize : Can't cd to '%s' - " 161 cow_printf("absolutize : Can't cd to '%s' - "
158 "errno = %d\n", from, errno); 162 "errno = %d\n", from, errno);
159 return(-1); 163 return -1;
160 } 164 }
161 *slash = '/'; 165 *slash = '/';
162 if(getcwd(to, size) == NULL){ 166 if (getcwd(to, size) == NULL) {
163 cow_printf("absolutize : unable to get cwd of '%s' - " 167 cow_printf("absolutize : unable to get cwd of '%s' - "
164 "errno = %d\n", from, errno); 168 "errno = %d\n", from, errno);
165 return(-1); 169 return -1;
166 } 170 }
167 remaining = size - strlen(to); 171 remaining = size - strlen(to);
168 if(strlen(slash) + 1 > remaining){ 172 if (strlen(slash) + 1 > remaining) {
169 cow_printf("absolutize : unable to fit '%s' into %d " 173 cow_printf("absolutize : unable to fit '%s' into %d "
170 "chars\n", from, size); 174 "chars\n", from, size);
171 return(-1); 175 return -1;
172 } 176 }
173 strcat(to, slash); 177 strcat(to, slash);
174 } 178 }
175 else { 179 else {
176 if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ 180 if (strlen(save_cwd) + 1 + strlen(from) + 1 > size) {
177 cow_printf("absolutize : unable to fit '%s' into %d " 181 cow_printf("absolutize : unable to fit '%s' into %d "
178 "chars\n", from, size); 182 "chars\n", from, size);
179 return(-1); 183 return -1;
180 } 184 }
181 strcpy(to, save_cwd); 185 strcpy(to, save_cwd);
182 strcat(to, "/"); 186 strcat(to, "/");
183 strcat(to, from); 187 strcat(to, from);
184 } 188 }
185 chdir(save_cwd); 189 chdir(save_cwd);
186 return(0); 190 return 0;
187} 191}
188 192
189int write_cow_header(char *cow_file, int fd, char *backing_file, 193int write_cow_header(char *cow_file, int fd, char *backing_file,
@@ -194,22 +198,23 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
194 int err; 198 int err;
195 199
196 err = cow_seek_file(fd, 0); 200 err = cow_seek_file(fd, 0);
197 if(err < 0){ 201 if (err < 0) {
198 cow_printf("write_cow_header - lseek failed, err = %d\n", -err); 202 cow_printf("write_cow_header - lseek failed, err = %d\n", -err);
199 goto out; 203 goto out;
200 } 204 }
201 205
202 err = -ENOMEM; 206 err = -ENOMEM;
203 header = cow_malloc(sizeof(*header)); 207 header = cow_malloc(sizeof(*header));
204 if(header == NULL){ 208 if (header == NULL) {
205 cow_printf("write_cow_header - failed to allocate COW V3 header\n"); 209 cow_printf("write_cow_header - failed to allocate COW V3 "
210 "header\n");
206 goto out; 211 goto out;
207 } 212 }
208 header->magic = htonl(COW_MAGIC); 213 header->magic = htonl(COW_MAGIC);
209 header->version = htonl(COW_VERSION); 214 header->version = htonl(COW_VERSION);
210 215
211 err = -EINVAL; 216 err = -EINVAL;
212 if(strlen(backing_file) > sizeof(header->backing_file) - 1){ 217 if (strlen(backing_file) > sizeof(header->backing_file) - 1) {
213 /* Below, %zd is for a size_t value */ 218 /* Below, %zd is for a size_t value */
214 cow_printf("Backing file name \"%s\" is too long - names are " 219 cow_printf("Backing file name \"%s\" is too long - names are "
215 "limited to %zd characters\n", backing_file, 220 "limited to %zd characters\n", backing_file,
@@ -217,12 +222,12 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
217 goto out_free; 222 goto out_free;
218 } 223 }
219 224
220 if(absolutize(header->backing_file, sizeof(header->backing_file), 225 if (absolutize(header->backing_file, sizeof(header->backing_file),
221 backing_file)) 226 backing_file))
222 goto out_free; 227 goto out_free;
223 228
224 err = os_file_modtime(header->backing_file, &modtime); 229 err = os_file_modtime(header->backing_file, &modtime);
225 if(err < 0){ 230 if (err < 0) {
226 cow_printf("write_cow_header - backing file '%s' mtime " 231 cow_printf("write_cow_header - backing file '%s' mtime "
227 "request failed, err = %d\n", header->backing_file, 232 "request failed, err = %d\n", header->backing_file,
228 -err); 233 -err);
@@ -230,7 +235,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
230 } 235 }
231 236
232 err = cow_file_size(header->backing_file, size); 237 err = cow_file_size(header->backing_file, size);
233 if(err < 0){ 238 if (err < 0) {
234 cow_printf("write_cow_header - couldn't get size of " 239 cow_printf("write_cow_header - couldn't get size of "
235 "backing file '%s', err = %d\n", 240 "backing file '%s', err = %d\n",
236 header->backing_file, -err); 241 header->backing_file, -err);
@@ -244,7 +249,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
244 header->cow_format = COW_BITMAP; 249 header->cow_format = COW_BITMAP;
245 250
246 err = cow_write_file(fd, header, sizeof(*header)); 251 err = cow_write_file(fd, header, sizeof(*header));
247 if(err != sizeof(*header)){ 252 if (err != sizeof(*header)) {
248 cow_printf("write_cow_header - write of header to " 253 cow_printf("write_cow_header - write of header to "
249 "new COW file '%s' failed, err = %d\n", cow_file, 254 "new COW file '%s' failed, err = %d\n", cow_file,
250 -err); 255 -err);
@@ -254,14 +259,14 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
254 out_free: 259 out_free:
255 cow_free(header); 260 cow_free(header);
256 out: 261 out:
257 return(err); 262 return err;
258} 263}
259 264
260int file_reader(__u64 offset, char *buf, int len, void *arg) 265int file_reader(__u64 offset, char *buf, int len, void *arg)
261{ 266{
262 int fd = *((int *) arg); 267 int fd = *((int *) arg);
263 268
264 return(pread(fd, buf, len, offset)); 269 return pread(fd, buf, len, offset);
265} 270}
266 271
267/* XXX Need to sanity-check the values read from the header */ 272/* XXX Need to sanity-check the values read from the header */
@@ -278,31 +283,29 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
278 unsigned long version, magic; 283 unsigned long version, magic;
279 284
280 header = cow_malloc(sizeof(*header)); 285 header = cow_malloc(sizeof(*header));
281 if(header == NULL){ 286 if (header == NULL) {
282 cow_printf("read_cow_header - Failed to allocate header\n"); 287 cow_printf("read_cow_header - Failed to allocate header\n");
283 return(-ENOMEM); 288 return -ENOMEM;
284 } 289 }
285 err = -EINVAL; 290 err = -EINVAL;
286 n = (*reader)(0, (char *) header, sizeof(*header), arg); 291 n = (*reader)(0, (char *) header, sizeof(*header), arg);
287 if(n < offsetof(typeof(header->v1), backing_file)){ 292 if (n < offsetof(typeof(header->v1), backing_file)) {
288 cow_printf("read_cow_header - short header\n"); 293 cow_printf("read_cow_header - short header\n");
289 goto out; 294 goto out;
290 } 295 }
291 296
292 magic = header->v1.magic; 297 magic = header->v1.magic;
293 if(magic == COW_MAGIC) { 298 if (magic == COW_MAGIC)
294 version = header->v1.version; 299 version = header->v1.version;
295 } 300 else if (magic == ntohl(COW_MAGIC))
296 else if(magic == ntohl(COW_MAGIC)){
297 version = ntohl(header->v1.version); 301 version = ntohl(header->v1.version);
298 }
299 /* No error printed because the non-COW case comes through here */ 302 /* No error printed because the non-COW case comes through here */
300 else goto out; 303 else goto out;
301 304
302 *version_out = version; 305 *version_out = version;
303 306
304 if(version == 1){ 307 if (version == 1) {
305 if(n < sizeof(header->v1)){ 308 if (n < sizeof(header->v1)) {
306 cow_printf("read_cow_header - failed to read V1 " 309 cow_printf("read_cow_header - failed to read V1 "
307 "header\n"); 310 "header\n");
308 goto out; 311 goto out;
@@ -314,8 +317,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
314 *align_out = *sectorsize_out; 317 *align_out = *sectorsize_out;
315 file = header->v1.backing_file; 318 file = header->v1.backing_file;
316 } 319 }
317 else if(version == 2){ 320 else if (version == 2) {
318 if(n < sizeof(header->v2)){ 321 if (n < sizeof(header->v2)) {
319 cow_printf("read_cow_header - failed to read V2 " 322 cow_printf("read_cow_header - failed to read V2 "
320 "header\n"); 323 "header\n");
321 goto out; 324 goto out;
@@ -328,8 +331,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
328 file = header->v2.backing_file; 331 file = header->v2.backing_file;
329 } 332 }
330 /* This is very subtle - see above at union cow_header definition */ 333 /* This is very subtle - see above at union cow_header definition */
331 else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){ 334 else if (version == 3 && (*((int*)header->v3.backing_file) != 0)) {
332 if(n < sizeof(header->v3)){ 335 if (n < sizeof(header->v3)) {
333 cow_printf("read_cow_header - failed to read V3 " 336 cow_printf("read_cow_header - failed to read V3 "
334 "header\n"); 337 "header\n");
335 goto out; 338 goto out;
@@ -345,17 +348,18 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
345 *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); 348 *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
346 file = header->v3.backing_file; 349 file = header->v3.backing_file;
347 } 350 }
348 else if(version == 3){ 351 else if (version == 3) {
349 cow_printf("read_cow_header - broken V3 file with" 352 cow_printf("read_cow_header - broken V3 file with"
350 " 64-bit layout - recovering content.\n"); 353 " 64-bit layout - recovering content.\n");
351 354
352 if(n < sizeof(header->v3_b)){ 355 if (n < sizeof(header->v3_b)) {
353 cow_printf("read_cow_header - failed to read V3 " 356 cow_printf("read_cow_header - failed to read V3 "
354 "header\n"); 357 "header\n");
355 goto out; 358 goto out;
356 } 359 }
357 360
358 /* this was used until Dec2005 - 64bits are needed to represent 361 /*
362 * this was used until Dec2005 - 64bits are needed to represent
359 * 2038+. I.e. we can safely do this truncating cast. 363 * 2038+. I.e. we can safely do this truncating cast.
360 * 364 *
361 * Additionally, we must use ntohl() instead of ntohll(), since 365 * Additionally, we must use ntohl() instead of ntohll(), since
@@ -381,7 +385,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
381 } 385 }
382 err = -ENOMEM; 386 err = -ENOMEM;
383 *backing_file_out = cow_strdup(file); 387 *backing_file_out = cow_strdup(file);
384 if(*backing_file_out == NULL){ 388 if (*backing_file_out == NULL) {
385 cow_printf("read_cow_header - failed to allocate backing " 389 cow_printf("read_cow_header - failed to allocate backing "
386 "file\n"); 390 "file\n");
387 goto out; 391 goto out;
@@ -389,7 +393,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
389 err = 0; 393 err = 0;
390 out: 394 out:
391 cow_free(header); 395 cow_free(header);
392 return(err); 396 return err;
393} 397}
394 398
395int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, 399int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
@@ -402,7 +406,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
402 406
403 err = write_cow_header(cow_file, fd, backing_file, sectorsize, 407 err = write_cow_header(cow_file, fd, backing_file, sectorsize,
404 alignment, &size); 408 alignment, &size);
405 if(err) 409 if (err)
406 goto out; 410 goto out;
407 411
408 *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); 412 *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
@@ -411,17 +415,18 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
411 415
412 offset = *data_offset_out + size - sizeof(zero); 416 offset = *data_offset_out + size - sizeof(zero);
413 err = cow_seek_file(fd, offset); 417 err = cow_seek_file(fd, offset);
414 if(err < 0){ 418 if (err < 0) {
415 cow_printf("cow bitmap lseek failed : err = %d\n", -err); 419 cow_printf("cow bitmap lseek failed : err = %d\n", -err);
416 goto out; 420 goto out;
417 } 421 }
418 422
419 /* does not really matter how much we write it is just to set EOF 423 /*
424 * does not really matter how much we write it is just to set EOF
420 * this also sets the entire COW bitmap 425 * this also sets the entire COW bitmap
421 * to zero without having to allocate it 426 * to zero without having to allocate it
422 */ 427 */
423 err = cow_write_file(fd, &zero, sizeof(zero)); 428 err = cow_write_file(fd, &zero, sizeof(zero));
424 if(err != sizeof(zero)){ 429 if (err != sizeof(zero)) {
425 cow_printf("Write of bitmap to new COW file '%s' failed, " 430 cow_printf("Write of bitmap to new COW file '%s' failed, "
426 "err = %d\n", cow_file, -err); 431 "err = %d\n", cow_file, -err);
427 if (err >= 0) 432 if (err >= 0)
@@ -429,15 +434,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
429 goto out; 434 goto out;
430 } 435 }
431 436
432 return(0); 437 return 0;
433
434 out: 438 out:
435 return(err); 439 return err;
436} 440}
437
438/*
439 * ---------------------------------------------------------------------------
440 * Local variables:
441 * c-file-style: "linux"
442 * End:
443 */