Changeset View
Standalone View
lib/libstand/dosfs.c
Context not available. | |||||
#define DEPSEC 16 /* directory entries per sector */ | #define DEPSEC 16 /* directory entries per sector */ | ||||
#define DSHIFT 4 /* DEPSEC shift */ | #define DSHIFT 4 /* DEPSEC shift */ | ||||
#define LOCLUS 2 /* lowest cluster number */ | #define LOCLUS 2 /* lowest cluster number */ | ||||
#define FATBLKSZ 0x20000 /* size of block in the FAT cache buffer */ | |||||
/* DOS "BIOS Parameter Block" */ | /* DOS "BIOS Parameter Block" */ | ||||
typedef struct { | typedef struct { | ||||
Context not available. | |||||
((u_int)cv2((de)->dex.h_clus) << 16) | \ | ((u_int)cv2((de)->dex.h_clus) << 16) | \ | ||||
cv2((de)->clus)) | cv2((de)->clus)) | ||||
/* | |||||
* fat cache metadata | |||||
*/ | |||||
struct fatcache { | |||||
int unit; /* disk unit number */ | |||||
int size; /* buffer (and fat) size in sectors */ | |||||
u_char *buf; | |||||
}; | |||||
static struct fatcache fat; | |||||
static int dosunmount(DOS_FS *); | |||||
static int parsebs(DOS_FS *, DOS_BS *); | static int parsebs(DOS_FS *, DOS_BS *); | ||||
static int namede(DOS_FS *, const char *, DOS_DE **); | static int namede(DOS_FS *, const char *, DOS_DE **); | ||||
static int lookup(DOS_FS *, u_int, const char *, DOS_DE **); | static int lookup(DOS_FS *, u_int, const char *, DOS_DE **); | ||||
Context not available. | |||||
static int ioread(DOS_FS *, u_int, void *, u_int); | static int ioread(DOS_FS *, u_int, void *, u_int); | ||||
static int ioget(struct open_file *, daddr_t, void *, u_int); | static int ioget(struct open_file *, daddr_t, void *, u_int); | ||||
static void | static int | ||||
dos_read_fat(DOS_FS *fs, struct open_file *fd) | dos_read_fatblk(DOS_FS *fs, struct open_file *fd, u_int blknum) | ||||
{ | { | ||||
struct devdesc *dd = fd->f_devdata; | int err; | ||||
u_int io_size; | |||||
daddr_t offset_in_fat, max_offset_in_fat; | |||||
if (fat.buf != NULL) { /* can we reuse old buffer? */ | offset_in_fat = ((daddr_t)blknum) * FATBLKSZ; | ||||
if (fat.size != fs->spf) { | max_offset_in_fat = secbyt(fs->spf); | ||||
free(fat.buf); /* no, free old buffer */ | io_size = FATBLKSZ; | ||||
fat.buf = NULL; | if (offset_in_fat > max_offset_in_fat) | ||||
} | offset_in_fat = max_offset_in_fat; | ||||
if (offset_in_fat + io_size > max_offset_in_fat) | |||||
io_size = ((u_int)(max_offset_in_fat - offset_in_fat)); | |||||
if (io_size != 0) { | |||||
err = ioget(fd, fs->lsnfat + bytsec(offset_in_fat), | |||||
tsoome: cstyle: opening { should be on the same line with if. Same below. | |||||
fs->fatbuf, io_size); | |||||
Done Inline ActionsAlso note it is good to fit in 80 chars. tsoome: Also note it is good to fit in 80 chars. | |||||
tsoomeUnsubmitted Done Inline ActionsThere is another problem - normally the indentation is tab and continuation is 4 spaces, however this file is older one and built by different logic - with all cases 4 position (replaced by tabs if needed). So in this case, the tab + 4 spaces is probably the thing you need. We do not align to first function argument. hint: man style ;) tsoome: There is another problem - normally the indentation is tab and continuation is 4 spaces… | |||||
if (err != 0) { | |||||
fs->fatbuf_blknum = ((u_int)(-1)); | |||||
return (err); | |||||
} | |||||
} | } | ||||
if (io_size < FATBLKSZ) | |||||
memset(fs->fatbuf + io_size, 0, FATBLKSZ - io_size); | |||||
if (fat.buf == NULL) | fs->fatbuf_blknum = blknum; | ||||
fat.buf = malloc(secbyt(fs->spf)); | return (0); | ||||
if (fat.buf != NULL) { | |||||
if (ioget(fd, fs->lsnfat, fat.buf, secbyt(fs->spf)) == 0) { | |||||
fat.size = fs->spf; | |||||
fat.unit = dd->d_unit; | |||||
return; | |||||
} | |||||
} | |||||
if (fat.buf != NULL) /* got IO error */ | |||||
free(fat.buf); | |||||
fat.buf = NULL; | |||||
fat.unit = -1; /* impossible unit */ | |||||
fat.size = 0; | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
dos_mount(DOS_FS *fs, struct open_file *fd) | dos_mount(DOS_FS *fs, struct open_file *fd) | ||||
{ | { | ||||
int err; | int err; | ||||
struct devdesc *dd = fd->f_devdata; | |||||
u_char *buf; | u_char *buf; | ||||
bzero(fs, sizeof(DOS_FS)); | bzero(fs, sizeof(DOS_FS)); | ||||
fs->fd = fd; | fs->fd = fd; | ||||
if ((err = !(buf = malloc(secbyt(1))) ? errno : 0) || | if ((buf = malloc(secbyt(1))) == NULL) { | ||||
(err = ioget(fs->fd, 0, buf, secbyt(1))) || | err = errno; | ||||
free(fs); | |||||
Done Inline ActionsI was reviewing this on illumos with tsoome and noticed a problem with the free() logic here. He asked I relay this here. In general, if we're freeing something that's not from the function we allocate it, we need to think twice. It turns out that dos_mount() is only called by dos_open(). And while dos_open() does free fs (somewhat confusingly), none of the other functions that dos_open() calls do free fs, and thus we can have memory leaks in those error cases. I think this will be more straightforward if you don't try and free fs here at all and instead deal with its memory lifetime consistently in dos_open(). rm_fingolfin.org: I was reviewing this on illumos with tsoome and noticed a problem with the free() logic here. | |||||
return (err); | |||||
} | |||||
Done Inline ActionsThis is not your change, but can you remove if there - our free() does check for NULL. tsoome: This is not your change, but can you remove if there - our free() does check for NULL. | |||||
if ((err = ioget(fs->fd, 0, buf, secbyt(1))) || | |||||
(err = parsebs(fs, (DOS_BS *)buf))) { | (err = parsebs(fs, (DOS_BS *)buf))) { | ||||
if (buf != NULL) | free(buf); | ||||
free(buf); | free(fs); | ||||
(void)dosunmount(fs); | |||||
return (err); | return (err); | ||||
} | } | ||||
free(buf); | free(buf); | ||||
if (fat.buf == NULL || fat.unit != dd->d_unit) | if ((fs->fatbuf = malloc(FATBLKSZ)) == NULL) { | ||||
dos_read_fat(fs, fd); | err = errno; | ||||
Done Inline Actionsspace after return. tsoome: space after return. | |||||
free(fs); | |||||
return (err); | |||||
} | |||||
err = dos_read_fatblk(fs, fd, 0); | |||||
if (err != 0) { | |||||
free(fs->fatbuf); | |||||
Done Inline Actionsspace after return. tsoome: space after return. | |||||
free(fs); | |||||
return (err); | |||||
} | |||||
fs->root = dot[0]; | fs->root = dot[0]; | ||||
fs->root.name[0] = ' '; | fs->root.name[0] = ' '; | ||||
Context not available. | |||||
static int | static int | ||||
dos_unmount(DOS_FS *fs) | dos_unmount(DOS_FS *fs) | ||||
{ | { | ||||
int err; | |||||
if (fs->links) | if (fs->links) | ||||
return (EBUSY); | return (EBUSY); | ||||
if ((err = dosunmount(fs))) | free(fs->fatbuf); | ||||
return (err); | |||||
return (0); | |||||
} | |||||
/* | |||||
* Common code shared by dos_mount() and dos_unmount() | |||||
*/ | |||||
static int | |||||
dosunmount(DOS_FS *fs) | |||||
{ | |||||
free(fs); | free(fs); | ||||
return (0); | return (0); | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
/* | /* | ||||
* Get next cluster in cluster chain. Use in core fat cache unless another | * Get next cluster in cluster chain. Use in core fat cache unless | ||||
* device replaced it. | * the number of current 128K block in FAT has changed. | ||||
*/ | */ | ||||
static int | static int | ||||
fatget(DOS_FS *fs, u_int *c) | fatget(DOS_FS *fs, u_int *c) | ||||
{ | { | ||||
Done Inline Actionsu_char *p_entry; tsoome: u_char *p_entry; | |||||
u_char buf[4]; | u_char buf[4]; | ||||
u_int x, offset, n, nbyte; | u_int x, offset, blknum, nbyte; | ||||
struct devdesc *dd = fs->fd->f_devdata; | int err; | ||||
int err = 0; | |||||
if (fat.unit != dd->d_unit) { | |||||
/* fat cache was changed to another device, don't use it */ | |||||
err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf, | |||||
fs->fatsz != 32 ? 2 : 4); | |||||
if (err) | |||||
return (err); | |||||
} else { | |||||
offset = fatoff(fs->fatsz, *c); | |||||
nbyte = fs->fatsz != 32 ? 2 : 4; | |||||
Done Inline Actionsno parens needed tsoome: no parens needed | |||||
if (offset + nbyte > secbyt(fat.size)) | offset = fatoff(fs->fatsz, *c); | ||||
return (EINVAL); | nbyte = fs->fatsz != 32 ? 2 : 4; | ||||
memcpy(buf, fat.buf + offset, nbyte); | if (offset + nbyte > secbyt(fs->spf)) | ||||
return (EINVAL); | |||||
blknum = offset / FATBLKSZ; | |||||
offset %= FATBLKSZ; | |||||
if (offset + nbyte > FATBLKSZ) | |||||
return (EINVAL); | |||||
Done Inline Actionscstyle: { should be with if. tsoome: cstyle: { should be with if. | |||||
if (blknum != fs->fatbuf_blknum) { | |||||
err = dos_read_fatblk(fs, fs->fd, blknum); | |||||
if (err != 0) | |||||
return (err); | |||||
} | } | ||||
memcpy(buf, fs->fatbuf + offset, nbyte); | |||||
x = fs->fatsz != 32 ? cv2(buf) : cv4(buf); | x = fs->fatsz != 32 ? cv2(buf) : cv4(buf); | ||||
*c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x; | *c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x; | ||||
Context not available. |
cstyle: opening { should be on the same line with if. Same below.