00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef lint
00032 static char copyright[] =
00033 "@(#) Copyright (c) 2002-2004\n\
00034 Netherlands Forensic Institute. All rights reserved.\n";
00035 #endif
00036
00037 #if defined(HAVE_CONFIG_H)
00038 #include <config.h>
00039 #endif
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <string.h>
00044
00045 #include "rdd.h"
00046 #include "reader.h"
00047
00048 #define MAX_LINE 128
00049 #define MAX_FAULT 8
00050
00051 typedef unsigned short rngstate_t[3];
00052 typedef unsigned long seed_t;
00053
00054 typedef struct _RDDFAULT
00055 {
00056 rdd_count_t meanpos;
00057 } RDDFAULT;
00058
00059 typedef struct _FAULTY_READER_STATE
00060 {
00061 RDD_READER *parent;
00062 RDDFAULT faults[MAX_FAULT];
00063 unsigned nfault;
00064 } FAULTY_READER_STATE;
00065
00066
00067
00068 static int
00069 rdd_faulty_read(RDD_READER *r, unsigned char *buf, unsigned nbyte, unsigned *nread);
00070 static int
00071 rdd_faulty_tell(RDD_READER *r, rdd_count_t *pos);
00072 static int
00073 rdd_faulty_seek(RDD_READER *r, rdd_count_t pos);
00074 static int
00075 rdd_faulty_close(RDD_READER *r, int recurse);
00076
00077 static RDD_READ_OPS faulty_read_ops = { rdd_faulty_read, rdd_faulty_tell, rdd_faulty_seek,
00078 rdd_faulty_close };
00079
00080 static int
00081 fault_compare(const void *p1, const void *p2)
00082 {
00083 const RDDFAULT *f1 = p1;
00084 const RDDFAULT *f2 = p2;
00085
00086 if (f1->meanpos < f2->meanpos)
00087 {
00088 return -1;
00089 }
00090 else if (f1->meanpos > f2->meanpos)
00091 {
00092 return 1;
00093 }
00094 else
00095 {
00096 return 0;
00097 }
00098 }
00099
00100 static void
00101 fault_init(RDDFAULT *f, rdd_count_t meanpos)
00102 {
00103 memset(f, '\000', sizeof(*f));
00104 f->meanpos = meanpos;
00105 }
00106
00107
00108
00109 static int
00110 read_faults(FILE *fp, FAULTY_READER_STATE *state)
00111 {
00112 char line[MAX_LINE];
00113 unsigned lineno;
00114 rdd_count_t pos;
00115
00116 for (lineno = 1; fgets(line, MAX_LINE, fp) != NULL; lineno++)
00117 {
00118 if (strlen(line) >= MAX_LINE - 1)
00119 {
00120 return RDD_ESYNTAX;
00121 }
00122
00123 if (sscanf(line, "%llu", &pos) != 1)
00124 {
00125 return RDD_ESYNTAX;
00126 }
00127
00128 if (state->nfault >= MAX_FAULT)
00129 {
00130 return RDD_ESPACE;
00131 }
00132 fault_init(&state->faults[state->nfault], pos);
00133 state->nfault++;
00134 }
00135 if (!feof(fp))
00136 {
00137 return RDD_ESYNTAX;
00138 }
00139
00140 return RDD_OK;
00141 }
00142
00143
00144
00145 int
00146 rdd_open_faulty_reader(RDD_READER **self, RDD_READER *parent, char *path)
00147 {
00148 RDD_READER *r = 0;
00149 FAULTY_READER_STATE *state = 0;
00150 FILE *fp = 0;
00151 int rc;
00152
00153 if (self == 0 || parent == 0 || path == 0)
00154 {
00155 return RDD_BADARG;
00156 }
00157
00158 rc = rdd_new_reader(&r, &faulty_read_ops, sizeof(FAULTY_READER_STATE));
00159 if (rc != RDD_OK)
00160 {
00161 return rc;
00162 }
00163
00164 if ((fp = fopen(path, "r")) == NULL)
00165 {
00166 free(r);
00167 return RDD_EOPEN;
00168 }
00169
00170 state = (FAULTY_READER_STATE *) r->state;
00171 state->parent = parent;
00172
00173 if ((rc = read_faults(fp, state)) != RDD_OK)
00174 {
00175 free(state);
00176 free(r);
00177 fclose(fp);
00178 return rc;
00179 }
00180
00181 if (fclose(fp) == EOF)
00182 {
00183 free(state);
00184 free(r);
00185 return RDD_ECLOSE;
00186 }
00187
00188
00189
00190
00191 qsort(state->faults, state->nfault, sizeof(RDDFAULT), &fault_compare);
00192
00193 *self = r;
00194 return RDD_OK;
00195
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 int
00215 rdd_faulty_read(RDD_READER *self, unsigned char *buf, unsigned nbyte, unsigned *nread)
00216 {
00217 FAULTY_READER_STATE *state = self->state;
00218 rdd_count_t pos;
00219 RDDFAULT *f;
00220 unsigned i;
00221 int rc;
00222
00223 if ((rc = rdd_reader_tell(state->parent, &pos)) != RDD_OK)
00224 {
00225 return rc;
00226 }
00227
00228 for (i = 0; i < state->nfault; i++)
00229 {
00230 f = &state->faults[i];
00231
00232 if (f->meanpos >= pos && f->meanpos < (pos + nbyte))
00233 {
00234 rc = rdd_reader_read(state->parent, buf, nbyte, nread);
00235 if (rc != RDD_OK)
00236 {
00237 return rc;
00238 }
00239
00240 if (f->meanpos < (pos + *nread))
00241 {
00242
00243 return RDD_EREAD;
00244 }
00245 else
00246 {
00247 return RDD_OK;
00248 }
00249 }
00250 }
00251
00252
00253
00254 return rdd_reader_read(state->parent, buf, nbyte, nread);
00255 }
00256
00257 int
00258 rdd_faulty_tell(RDD_READER *self, rdd_count_t *pos)
00259 {
00260 FAULTY_READER_STATE *state = self->state;
00261
00262 return rdd_reader_tell(state->parent, pos);
00263 }
00264
00265 int
00266 rdd_faulty_seek(RDD_READER *self, rdd_count_t pos)
00267 {
00268 FAULTY_READER_STATE *state = self->state;
00269
00270 return rdd_reader_seek(state->parent, pos);
00271 }
00272
00273 int
00274 rdd_faulty_close(RDD_READER *self, int recurse)
00275 {
00276 FAULTY_READER_STATE *state = self->state;
00277
00278 if (recurse)
00279 {
00280 return rdd_reader_close(state->parent, 1);
00281 }
00282 else
00283 {
00284 return RDD_OK;
00285 }
00286 }