static int root_map(File_t *This, off_t where, size_t *len, int mode, mt_off_t *res) { Fs_t *Fs = This->Fs; if(Fs->dir_len * Fs->sector_size < where) { *len = 0; errno = ENOSPC; return -2; } maximize(*len, Fs->dir_len * Fs->sector_size - where); if (*len == 0) return 0; *res = sectorsToBytes((Stream_t*)Fs, Fs->dir_start) + where; return 1; }
static int root_map(struct File_t *This, off_t where, size_t *len, int UNUSED(mode), off_t *res) { struct Fs_t *Fs = This->Fs; if(Fs->dir_len * Fs->sector_size < (size_t) where) { *len = 0; errno = ENOSPC; return -2; } maximize(*len, Fs->dir_len * Fs->sector_size - where); if (*len == 0) return 0; *res = sectorsToBytes((struct Stream_t*)Fs, Fs->dir_start) + where; return 1; }
static int scan(Fs_t *Fs, Stream_t *dev, long cluster, unsigned int badClus, char *buffer, int write) { off_t start; off_t ret; off_t pos; int bad=0; if(Fs->fat_decode((Fs_t*)Fs, cluster)) /* cluster busy, or already marked */ return 0; start = (cluster - 2) * Fs->cluster_size + Fs->clus_start; pos = sectorsToBytes((Stream_t*)Fs, start); if(write) { ret = force_write(dev, buffer, pos, in_len); if(ret < in_len ) bad = 1; } else { ret = force_read(dev, in_buf, pos, in_len); if(ret < in_len ) bad = 1; else if(buffer) { int i; for(i=0; i<in_len; i++) if(in_buf[i] != buffer[i]) { bad = 1; break; } } } if(bad) { printf("Bad cluster %ld found\n", cluster); fatEncode((Fs_t*)Fs, cluster, badClus); return 1; } return 0; }
static int normal_map(File_t *This, off_t where, size_t *len, int mode, mt_off_t *res) { int offset; off_t end; int NrClu; /* number of clusters to read */ unsigned int RelCluNr; unsigned int CurCluNr; unsigned int NewCluNr; unsigned int AbsCluNr; int clus_size; Fs_t *Fs = This->Fs; *res = 0; clus_size = Fs->cluster_size * Fs->sector_size; offset = where % clus_size; if (mode == MT_READ) maximize(*len, This->FileSize - where); if (*len == 0 ) return 0; if (This->FirstAbsCluNr < 2){ if( mode == MT_READ || *len == 0){ *len = 0; return 0; } NewCluNr = get_next_free_cluster(This->Fs, 1); if (NewCluNr == 1 ){ errno = ENOSPC; return -2; } hash_remove(filehash, (void *) This, This->hint); This->FirstAbsCluNr = NewCluNr; hash_add(filehash, (void *) This, &This->hint); fatAllocate(This->Fs, NewCluNr, Fs->end_fat); } RelCluNr = where / clus_size; if (RelCluNr >= This->PreviousRelCluNr){ CurCluNr = This->PreviousRelCluNr; AbsCluNr = This->PreviousAbsCluNr; } else { CurCluNr = 0; AbsCluNr = This->FirstAbsCluNr; } NrClu = (offset + *len - 1) / clus_size; while (CurCluNr <= RelCluNr + NrClu){ if (CurCluNr == RelCluNr){ /* we have reached the beginning of our zone. Save * coordinates */ This->PreviousRelCluNr = RelCluNr; This->PreviousAbsCluNr = AbsCluNr; } NewCluNr = fatDecode(This->Fs, AbsCluNr); if (NewCluNr == 1 || NewCluNr == 0){ fprintf(stderr,"Fat problem while decoding %d %x\n", AbsCluNr, NewCluNr); exit(1); } if(CurCluNr == RelCluNr + NrClu) break; if (NewCluNr > Fs->last_fat && mode == MT_WRITE){ /* if at end, and writing, extend it */ NewCluNr = get_next_free_cluster(This->Fs, AbsCluNr); if (NewCluNr == 1 ){ /* no more space */ errno = ENOSPC; return -2; } fatAppend(This->Fs, AbsCluNr, NewCluNr); } if (CurCluNr < RelCluNr && NewCluNr > Fs->last_fat){ *len = 0; return 0; } if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1) break; CurCluNr++; AbsCluNr = NewCluNr; if(loopDetect(This, CurCluNr, AbsCluNr)) { errno = EIO; return -2; } } maximize(*len, (1 + CurCluNr - RelCluNr) * clus_size - offset); end = where + *len; if(batchmode && mode == MT_WRITE && end >= This->FileSize) { *len += ROUND_UP(end, clus_size) - end; } if((*len + offset) / clus_size + This->PreviousAbsCluNr-2 > Fs->num_clus) { fprintf(stderr, "cluster too big\n"); exit(1); } *res = sectorsToBytes((Stream_t*)Fs, (This->PreviousAbsCluNr-2) * Fs->cluster_size + Fs->clus_start) + offset; return 1; }
void mbadblocks(int argc, char **argv, int type) { unsigned int i; unsigned int startSector=2; unsigned int endSector=0; struct MainParam_t mp; Fs_t *Fs; Stream_t *Dir; int ret; char *filename = NULL; char c; unsigned int badClus; int sectorMode=0; int writeMode=0; while ((c = getopt(argc, argv, "i:s:cwS:E:")) != EOF) { switch(c) { case 'i': set_cmd_line_image(optarg, 0); break; case 'c': checkListTwice(filename); filename = strdup(optarg); break; case 's': checkListTwice(filename); filename = strdup(optarg); sectorMode = 1; break; case 'S': startSector = atol(optarg); break; case 'E': endSector = atol(optarg); break; case 'w': writeMode = 1; break; case 'h': usage(0); default: usage(1); } } if (argc != optind+1 || !argv[optind][0] || argv[optind][1] != ':' || argv[optind][2]) { usage(1); } init_mp(&mp); Dir = open_root_dir(argv[optind][0], O_RDWR, NULL); if (!Dir) { fprintf(stderr,"%s: Cannot initialize drive\n", argv[0]); exit(1); } Fs = (Fs_t *)GetFs(Dir); in_len = Fs->cluster_size * Fs->sector_size; in_buf = malloc(in_len); if(!in_buf) { printOom(); ret = 1; goto exit_0; } if(writeMode) { int i; pat_buf=malloc(in_len * N_PATTERN); if(!pat_buf) { printOom(); ret = 1; goto exit_0; } srandom(time(NULL)); for(i=0; i < in_len * N_PATTERN; i++) { pat_buf[i] = random(); } } for(i=0; i < Fs->clus_start; i++ ){ ret = READS(Fs->Next, in_buf, sectorsToBytes((Stream_t*)Fs, i), Fs->sector_size); if( ret < 0 ){ perror("early error"); goto exit_0; } if(ret < (signed int) Fs->sector_size){ fprintf(stderr,"end of file in file_read\n"); ret = 1; goto exit_0; } } ret = 0; badClus = Fs->last_fat + 1; if(startSector < 2) startSector = 2; if(endSector > Fs->num_clus + 2 || endSector <= 0) endSector = Fs->num_clus + 2; if(filename) { char line[80]; FILE *f = fopen(filename, "r"); if(f == NULL) { fprintf(stderr, "Could not open %s (%s)\n", filename, strerror(errno)); ret = 1; goto exit_0; } while(fgets(line, sizeof(line), f)) { char *ptr = line + strspn(line, " \t"); long offset = strtoul(ptr, 0, 0); if(sectorMode) offset = (offset-Fs->clus_start)/Fs->cluster_size + 2; if(offset < 2) { fprintf(stderr, "Sector before start\n"); } else if(offset >= Fs->num_clus) { fprintf(stderr, "Sector beyond end\n"); } else { mark(Fs, offset, badClus); ret = 1; } } } else { Stream_t *dev; dev = Fs->Next; if(dev->Next) dev = dev->Next; in_len = Fs->cluster_size * Fs->sector_size; if(writeMode) { /* Write pattern */ for(i=startSector; i< endSector; i++){ if(got_signal) break; progress(i, Fs->num_clus); ret |= scan(Fs, dev, i, badClus, pat_buf + in_len * (i % N_PATTERN), 1); } /* Flush cache, so that we are sure we read the data back from disk, rather than from the cache */ if(!got_signal) DISCARD(dev); /* Read data back, and compare to pattern */ for(i=startSector; i< endSector; i++){ if(got_signal) break; progress(i, Fs->num_clus); ret |= scan(Fs, dev, i, badClus, pat_buf + in_len * (i % N_PATTERN), 0); } } else { for(i=startSector; i< endSector; i++){ if(got_signal) break; progress(i, Fs->num_clus); ret |= scan(Fs, dev, i, badClus, NULL, 0); } } } exit_0: FREE(&Dir); exit(ret); }