Changeset View
Changeset View
Standalone View
Standalone View
stand/libsa/ufs.c
Show First 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/disklabel.h> | #include <sys/disklabel.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <ufs/ufs/dinode.h> | #include <ufs/ufs/dinode.h> | ||||
#include <ufs/ufs/dir.h> | #include <ufs/ufs/dir.h> | ||||
#include <ufs/ffs/fs.h> | #include <ufs/ffs/fs.h> | ||||
#include "stand.h" | #include "stand.h" | ||||
#include "disk.h" | |||||
#include "string.h" | #include "string.h" | ||||
static int ufs_open(const char *path, struct open_file *f); | static int ufs_open(const char *path, struct open_file *f); | ||||
static int ufs_write(struct open_file *f, const void *buf, size_t size, | static int ufs_write(struct open_file *f, const void *buf, size_t size, | ||||
size_t *resid); | size_t *resid); | ||||
static int ufs_close(struct open_file *f); | static int ufs_close(struct open_file *f); | ||||
static int ufs_read(struct open_file *f, void *buf, size_t size, size_t *resid); | static int ufs_read(struct open_file *f, void *buf, size_t size, size_t *resid); | ||||
static off_t ufs_seek(struct open_file *f, off_t offset, int where); | static off_t ufs_seek(struct open_file *f, off_t offset, int where); | ||||
static int ufs_stat(struct open_file *f, struct stat *sb); | static int ufs_stat(struct open_file *f, struct stat *sb); | ||||
static int ufs_readdir(struct open_file *f, struct dirent *d); | static int ufs_readdir(struct open_file *f, struct dirent *d); | ||||
static int ufs_mount(const char *dev, const char *path, void **data); | |||||
static int ufs_unmount(const char *dev, void *data); | |||||
struct fs_ops ufs_fsops = { | struct fs_ops ufs_fsops = { | ||||
"ufs", | .fs_name = "ufs", | ||||
ufs_open, | .fo_open = ufs_open, | ||||
ufs_close, | .fo_close = ufs_close, | ||||
ufs_read, | .fo_read = ufs_read, | ||||
ufs_write, | .fo_write = ufs_write, | ||||
ufs_seek, | .fo_seek = ufs_seek, | ||||
ufs_stat, | .fo_stat = ufs_stat, | ||||
ufs_readdir | .fo_readdir = ufs_readdir, | ||||
.fo_mount = ufs_mount, | |||||
.fo_unmount = ufs_unmount | |||||
}; | }; | ||||
/* | /* | ||||
* In-core open file. | * In-core open file. | ||||
*/ | */ | ||||
struct file { | struct file { | ||||
off_t f_seekp; /* seek pointer */ | off_t f_seekp; /* seek pointer */ | ||||
struct fs *f_fs; /* pointer to super-block */ | struct fs *f_fs; /* pointer to super-block */ | ||||
Show All 13 Lines | struct file { | ||||
char *f_buf; /* buffer for data block */ | char *f_buf; /* buffer for data block */ | ||||
size_t f_buf_size; /* size of data block */ | size_t f_buf_size; /* size of data block */ | ||||
int f_inumber; /* inumber */ | int f_inumber; /* inumber */ | ||||
}; | }; | ||||
#define DIP(fp, field) \ | #define DIP(fp, field) \ | ||||
((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \ | ((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \ | ||||
(fp)->f_di.di1.field : (fp)->f_di.di2.field) | (fp)->f_di.di1.field : (fp)->f_di.di2.field) | ||||
typedef struct ufs_mnt { | |||||
char *um_dev; | |||||
int um_fd; | |||||
STAILQ_ENTRY(ufs_mnt) um_link; | |||||
} ufs_mnt_t; | |||||
typedef STAILQ_HEAD(ufs_mnt_list, ufs_mnt) ufs_mnt_list_t; | |||||
static ufs_mnt_list_t mnt_list = STAILQ_HEAD_INITIALIZER(mnt_list); | |||||
static int read_inode(ino_t, struct open_file *); | static int read_inode(ino_t, struct open_file *); | ||||
static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *); | static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *); | ||||
static int buf_read_file(struct open_file *, char **, size_t *); | static int buf_read_file(struct open_file *, char **, size_t *); | ||||
static int buf_write_file(struct open_file *, const char *, size_t *); | static int buf_write_file(struct open_file *, const char *, size_t *); | ||||
static int search_directory(char *, struct open_file *, ino_t *); | static int search_directory(char *, struct open_file *, ino_t *); | ||||
static int ufs_use_sa_read(void *, off_t, void **, int); | static int ufs_use_sa_read(void *, off_t, void **, int); | ||||
/* from ffs_subr.c */ | /* from ffs_subr.c */ | ||||
▲ Show 20 Lines • Show All 356 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
/* | /* | ||||
* Open a file. | * Open a file. | ||||
*/ | */ | ||||
static int | static int | ||||
ufs_open(upath, f) | ufs_open(const char *upath, struct open_file *f) | ||||
const char *upath; | |||||
struct open_file *f; | |||||
{ | { | ||||
char *cp, *ncp; | char *cp, *ncp; | ||||
int c; | int c; | ||||
ino_t inumber, parent_inumber; | ino_t inumber, parent_inumber; | ||||
struct file *fp; | struct file *fp; | ||||
struct fs *fs; | struct fs *fs; | ||||
int rc; | int rc; | ||||
int nlinks = 0; | int nlinks = 0; | ||||
char namebuf[MAXPATHLEN+1]; | char namebuf[MAXPATHLEN+1]; | ||||
char *buf = NULL; | char *buf = NULL; | ||||
char *path = NULL; | char *path = NULL; | ||||
const char *dev; | |||||
ufs_mnt_t *mnt; | |||||
/* allocate file system specific data structure */ | /* allocate file system specific data structure */ | ||||
fp = malloc(sizeof(struct file)); | fp = malloc(sizeof(struct file)); | ||||
bzero(fp, sizeof(struct file)); | bzero(fp, sizeof(struct file)); | ||||
f->f_fsdata = (void *)fp; | f->f_fsdata = (void *)fp; | ||||
dev = disk_fmtdev(f->f_devdata); | |||||
STAILQ_FOREACH(mnt, &mnt_list, um_link) { | |||||
if (strcmp(dev, mnt->um_dev) == 0) | |||||
break; | |||||
} | |||||
if (mnt == NULL) { | |||||
/* read super block */ | /* read super block */ | ||||
twiddle(1); | twiddle(1); | ||||
if ((rc = ffs_sbget(f, &fs, STDSB_NOHASHFAIL, "stand", | if ((rc = ffs_sbget(f, &fs, STDSB_NOHASHFAIL, "stand", | ||||
ufs_use_sa_read)) != 0) | ufs_use_sa_read)) != 0) | ||||
goto out; | goto out; | ||||
} else { | |||||
struct open_file *sbf; | |||||
struct file *sfp; | |||||
/* get superblock from mounted file system */ | |||||
sbf = fd2open_file(mnt->um_fd); | |||||
sfp = sbf->f_fsdata; | |||||
fs = sfp->f_fs; | |||||
} | |||||
fp->f_fs = fs; | fp->f_fs = fs; | ||||
/* | /* | ||||
* Calculate indirect block levels. | * Calculate indirect block levels. | ||||
*/ | */ | ||||
{ | { | ||||
ufs2_daddr_t mult; | ufs2_daddr_t mult; | ||||
int level; | int level; | ||||
mult = 1; | mult = 1; | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | ufs_open(const char *upath, struct open_file *f) | ||||
} | } | ||||
/* | /* | ||||
* Found terminal component. | * Found terminal component. | ||||
*/ | */ | ||||
rc = 0; | rc = 0; | ||||
fp->f_seekp = 0; | fp->f_seekp = 0; | ||||
out: | out: | ||||
if (buf) | |||||
free(buf); | free(buf); | ||||
if (path) | |||||
free(path); | free(path); | ||||
if (rc) { | if (rc) { | ||||
if (fp->f_buf) | |||||
free(fp->f_buf); | free(fp->f_buf); | ||||
if (fp->f_fs != NULL) { | |||||
if (mnt == NULL && fp->f_fs != NULL) { | |||||
free(fp->f_fs->fs_csp); | free(fp->f_fs->fs_csp); | ||||
free(fp->f_fs->fs_si); | free(fp->f_fs->fs_si); | ||||
free(fp->f_fs); | free(fp->f_fs); | ||||
} | } | ||||
free(fp); | free(fp); | ||||
} | } | ||||
return (rc); | return (rc); | ||||
} | } | ||||
Show All 19 Lines | if (buf_size != size) | ||||
return (EIO); | return (EIO); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ufs_close(f) | ufs_close(f) | ||||
struct open_file *f; | struct open_file *f; | ||||
{ | { | ||||
ufs_mnt_t *mnt; | |||||
struct file *fp = (struct file *)f->f_fsdata; | struct file *fp = (struct file *)f->f_fsdata; | ||||
int level; | int level; | ||||
char *dev; | |||||
f->f_fsdata = (void *)0; | f->f_fsdata = NULL; | ||||
if (fp == (struct file *)0) | if (fp == NULL) | ||||
return (0); | return (0); | ||||
for (level = 0; level < UFS_NIADDR; level++) { | for (level = 0; level < UFS_NIADDR; level++) { | ||||
if (fp->f_blk[level]) | |||||
free(fp->f_blk[level]); | free(fp->f_blk[level]); | ||||
} | } | ||||
if (fp->f_buf) | |||||
free(fp->f_buf); | free(fp->f_buf); | ||||
if (fp->f_fs != NULL) { | |||||
dev = disk_fmtdev(f->f_devdata); | |||||
STAILQ_FOREACH(mnt, &mnt_list, um_link) { | |||||
if (strcmp(dev, mnt->um_dev) == 0) | |||||
break; | |||||
} | |||||
if (mnt == NULL && fp->f_fs != NULL) { | |||||
free(fp->f_fs->fs_csp); | free(fp->f_fs->fs_csp); | ||||
free(fp->f_fs->fs_si); | free(fp->f_fs->fs_si); | ||||
free(fp->f_fs); | free(fp->f_fs); | ||||
} | } | ||||
free(fp); | free(fp); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Copy a portion of a file into kernel memory. | * Copy a portion of a file into kernel memory. | ||||
* Cross block boundaries when necessary. | * Cross block boundaries when necessary. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | again: | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
dp = (struct direct *)buf; | dp = (struct direct *)buf; | ||||
fp->f_seekp += dp->d_reclen; | fp->f_seekp += dp->d_reclen; | ||||
if (dp->d_ino == (ino_t)0) | if (dp->d_ino == (ino_t)0) | ||||
goto again; | goto again; | ||||
d->d_type = dp->d_type; | d->d_type = dp->d_type; | ||||
strcpy(d->d_name, dp->d_name); | strcpy(d->d_name, dp->d_name); | ||||
return (0); | |||||
} | |||||
static int | |||||
ufs_mount(const char *dev, const char *path, void **data) | |||||
{ | |||||
char *fs; | |||||
int fd = -1; | |||||
ufs_mnt_t *mnt; | |||||
mnt = calloc(1, sizeof(*mnt)); | |||||
if (mnt == NULL) | |||||
return (errno); | |||||
imp: In the mount code, we test against -1, but errno is going to be a small positive number so I… | |||||
Done Inline Actionsmalloc/calloc, memalign etc do get errno set from sbr() - when heap is full, sbrk() is called. At this time, the mount() code is considering fo_mount() result 0 success and anything else fail. tsoome: malloc/calloc, memalign etc do get errno set from sbr() - when heap is full, sbrk() is called. | |||||
mnt->um_fd = -1; | |||||
mnt->um_dev = strdup(dev); | |||||
if (mnt->um_dev == NULL) | |||||
goto done; | |||||
Done Inline ActionsI'm not sure where strdup sets errno on failure. It should be in malloc, but that's the same code path as calloc so same question. imp: I'm not sure where strdup sets errno on failure. It should be in malloc, but that's the same… | |||||
if (asprintf(&fs, "%s%s", dev, path) < 0) | |||||
goto done; | |||||
Done Inline ActionsSame question here too. Sorry to be so tedious :) imp: Same question here too. Sorry to be so tedious :) | |||||
mnt->um_fd = open(fs, O_RDONLY); | |||||
Done Inline ActionsAt least for open I can fund where we set errno :) imp: At least for open I can fund where we set errno :) | |||||
free(fs); | |||||
if (mnt->um_fd == -1) | |||||
goto done; | |||||
STAILQ_INSERT_TAIL(&mnt_list, mnt, um_link); | |||||
done: | |||||
if (errno != 0) { | |||||
impUnsubmitted Done Inline ActionsYou should set errno = 0 at the top of this routine, otherwise you can get stale versions of errno and think there was an error when there wasn't. imp: You should set errno = 0 at the top of this routine, otherwise you can get stale versions of… | |||||
free(mnt->um_dev); | |||||
if (fd >= 0) | |||||
close(fd); | |||||
free(mnt); | |||||
} else { | |||||
*data = mnt; | |||||
} | |||||
return (errno); | |||||
} | |||||
static int | |||||
ufs_unmount(const char *dev, void *data) | |||||
{ | |||||
ufs_mnt_t *mnt = data; | |||||
STAILQ_REMOVE(&mnt_list, mnt, ufs_mnt, um_link); | |||||
free(mnt->um_dev); | |||||
close(mnt->um_fd); | |||||
free(mnt); | |||||
return (0); | return (0); | ||||
} | } |
In the mount code, we test against -1, but errno is going to be a small positive number so I think that's a mismatch.
Though I'm not sure where errno gets set for a calloc failure since znalloc doesn't seem to set it...