/*
* Copyright (c) 2003-2014 University of Utah and the Flux Group.
*
* {{{EMULAB-LICENSE
*
* This file is part of the Emulab network testbed software.
*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this file. If not, see .
*
* }}}
*/
/*
* Glue to code from fsck_msdosfs
*/
#include
#include
#include
#include
#include
#include "sliceinfo.h"
#include "global.h"
#include "fat_glue.h"
static u_int32_t fat_offset, fat_limit;
static int fatsecpersec;
int
read_fatslice(int slice, iz_type stype, iz_lba start, iz_size size,
char *sfilename, int infd)
{
struct bootblock boot;
struct fatEntry *fat = NULL;
fat_offset = start;
if (size > 0)
fat_limit = start + size;
if (fat_lseek(infd, 0, SEEK_SET) == -1) {
warnx("FAT Slice %d: Could not seek to boot sector", slice+1);
return 1;
}
if (readboot(infd, &boot) != FSOK)
return 1;
if (debug)
fprintf(stderr, "FAT Slice %d: FAT%d filesystem found\n",
slice+1,
boot.ClustMask == CLUST32_MASK ? 32 :
boot.ClustMask == CLUST16_MASK ? 16 : 12);
fatsecpersec = boot.BytesPerSec / secsize;
if (fatsecpersec * secsize != boot.BytesPerSec) {
warnx("FAT Slice %d: FAT sector size (%d) not a multiple of %d",
slice+1, boot.BytesPerSec, secsize);
return 1;
}
if (readfat(infd, &boot,
boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat) != FSOK)
return 1;
free(fat);
if (debug)
fprintf(stderr, " NumFree %9d, NumClusters %9d\n",
boot.NumFree, boot.NumClusters);
return 0;
}
void
fat_addskip(struct bootblock *boot, int startcl, int ncl)
{
uint32_t start, size;
start = startcl * boot->SecPerClust + boot->ClusterOffset;
size = ncl * boot->SecPerClust;
if (fatsecpersec != 1) {
start /= fatsecpersec;
size /= fatsecpersec;
}
start += fat_offset;
assert(fat_limit == 0 || start + size <= fat_limit);
if (debug > 1)
fprintf(stderr, " CL%d-%d\t offset %9u, free %6u\n",
startcl, startcl + ncl - 1, start, size);
addskip(start, size);
}
#undef lseek
off_t
fat_lseek(int fd, off_t off, int whence)
{
off_t noff;
assert(whence == SEEK_SET);
off += sectobytes(fat_offset);
assert(fat_limit == 0 || off < sectobytes(fat_limit));
assert((off & (DEV_BSIZE-1)) == 0);
noff = lseek(fd, off, whence) - sectobytes(fat_offset);
assert(noff == (off_t)-1 || (noff & (DEV_BSIZE-1)) == 0);
return noff;
}