1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/* io.c - Virtual disk input/output */
/* Written 1993 by Werner Almesberger */
/*
* Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>
* Fixed nasty bug that caused every file with a name like
* xxxxxxxx.xxx to be treated as bad name that needed to be fixed.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "dosfsck.h"
#include "common.h"
#include "io.h"
typedef struct _change {
void *data;
unsigned int pos;
int size;
struct _change *next;
} CHANGE;
static CHANGE *changes,*last;
static int fd,did_change = 0;
void fs_open(char *path,int rw)
{
if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0)
pdie("open %s",path);
changes = last = NULL;
did_change = 0;
}
void fs_read(unsigned int pos,int size,void *data)
{
CHANGE *walk;
int got;
if (lseek(fd,pos,0) != pos) pdie("Seek to %d",pos);
if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %d",size,pos);
if (got != size) die("Got %d bytes instead of %d at %d",got,size,pos);
for (walk = changes; walk; walk = walk->next)
if (walk->pos < pos+size && walk->pos+walk->size > pos)
if (walk->pos < pos)
memcpy(data,(char *) walk->data+pos-walk->pos,min(size,
walk->size-pos+walk->pos));
else memcpy((char *) data+walk->pos-pos,walk->data,min(walk->size,
size+pos-walk->pos));
}
int fs_test(unsigned int pos,int size)
{
void *scratch;
int okay;
if (lseek(fd,pos,0) != pos) pdie("Seek to %d",pos);
scratch = alloc(size);
okay = read(fd,scratch,size) == size;
free(scratch);
return okay;
}
void fs_write(unsigned int pos,int size,void *data)
{
CHANGE *new;
int did;
if (write_immed) {
did_change = 1;
if (lseek(fd,pos,0) != pos) pdie("Seek to %d",pos);
if ((did = write(fd,data,size)) == size) return;
if (did < 0) pdie("Write %d bytes at %d",size,pos);
die("Wrote %d bytes instead of %d at %d",did,size,pos);
}
new = alloc(sizeof(CHANGE));
new->pos = pos;
memcpy(new->data = alloc(new->size = size),data,size);
new->next = NULL;
if (last) last->next = new;
else changes = new;
last = new;
}
static void fs_flush(void)
{
CHANGE *this;
int size;
while (changes) {
this = changes;
changes = changes->next;
if (lseek(fd,this->pos,0) != this->pos)
fprintf(stderr,"Seek to %d failed: %s\n Did not write %d bytes.\n",
this->pos,strerror(errno),this->size);
else if ((size = write(fd,this->data,this->size)) < 0)
fprintf(stderr,"Writing %d bytes at %d failed: %s\n",this->size,
this->pos,strerror(errno));
else if (size != this->size)
fprintf(stderr,"Wrote %d bytes instead of %d bytes at %d."
"\n",size,this->size,this->pos);
free(this->data);
free(this);
}
}
int fs_close(int write)
{
CHANGE *next;
int changed;
changed = !!changes;
if (write) fs_flush();
else while (changes) {
next = changes->next;
free(changes->data);
free(changes);
changes = next;
}
if (close(fd) < 0) pdie("closing file system");
return changed || did_change;
}
int fs_changed(void)
{
return !!changes || did_change;
}
|