Various changes made while offline.

 + bwrite sector argument is redundant; use b->sector.
 + reformatting of files for nicer PDF page breaks
 + distinguish between locked, unlocked inodes in type signatures
 + change FD_FILE to FD_INODE
 + move userinit (nee proc0init) to proc.c
 + move ROOTDEV to param.h
 + always parenthesize sizeof argument
This commit is contained in:
rsc 2007-08-22 06:01:32 +00:00
parent 3dcf889c1b
commit eaea18cb9c
25 changed files with 637 additions and 669 deletions

316
sysfile.c
View file

@ -11,7 +11,6 @@
#include "buf.h"
#include "fs.h"
#include "fsvar.h"
#include "elf.h"
#include "file.h"
#include "fcntl.h"
@ -51,27 +50,15 @@ fdalloc(struct file *f)
}
int
sys_pipe(void)
sys_read(void)
{
int *fd;
struct file *rf, *wf;
int fd0, fd1;
struct file *f;
int n;
char *cp;
if(argptr(0, (void*)&fd, 2*sizeof fd[0]) < 0)
if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &cp, n) < 0)
return -1;
if(pipe_alloc(&rf, &wf) < 0)
return -1;
fd0 = -1;
if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
if(fd0 >= 0)
cp->ofile[fd0] = 0;
fileclose(rf);
fileclose(wf);
return -1;
}
fd[0] = fd0;
fd[1] = fd1;
return 0;
return fileread(f, cp, n);
}
int
@ -87,15 +74,14 @@ sys_write(void)
}
int
sys_read(void)
sys_fstat(void)
{
struct file *f;
int n;
char *cp;
if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &cp, n) < 0)
struct stat *st;
if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0)
return -1;
return fileread(f, cp, n);
return filestat(f, st);
}
int
@ -111,6 +97,150 @@ sys_close(void)
return 0;
}
// Create the path new as a link to the same inode as old.
int
sys_link(void)
{
char name[DIRSIZ], *new, *old;
struct inode *dp, *ip;
struct uinode *ipu;
if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
return -1;
if((ip = ilock(namei(old))) == 0)
return -1;
if(ip->type == T_DIR){
iput(iunlock(ip));
return -1;
}
ip->nlink++;
iupdate(ip);
ipu = iunlock(ip); ip = 0;
if((dp = ilock(nameiparent(new, name))) == 0 ||
dp->dev != ipu->dev || dirlink(dp, name, ipu->inum) < 0){
if(dp)
iput(iunlock(dp));
ip = ilock(ipu);
ip->nlink--;
iupdate(ip);
iput(iunlock(ip));
return -1;
}
iput(iunlock(dp));
iput(ipu);
return 0;
}
// Is the directory dp empty except for "." and ".." ?
static int
isdirempty(struct inode *dp)
{
int off;
struct dirent de;
for(off=2*sizeof(de); off<dp->size; off+=sizeof(de)){
if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
panic("isdirempty: readi");
if(de.inum != 0)
return 0;
}
return 1;
}
int
sys_unlink(void)
{
struct inode *ip, *dp;
struct dirent de;
char name[DIRSIZ], *path;
uint off;
if(argstr(0, &path) < 0)
return -1;
if((dp = ilock(nameiparent(path, name))) == 0)
return -1;
// Cannot unlink "." or "..".
if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0){
iput(iunlock(dp));
return -1;
}
if((ip = ilock(dirlookup(dp, name, &off))) == 0){
iput(iunlock(dp));
return -1;
}
if(ip->nlink < 1)
panic("unlink: nlink < 1");
if(ip->type == T_DIR && !isdirempty(ip)){
iput(iunlock(ip));
iput(iunlock(dp));
return -1;
}
memset(&de, 0, sizeof(de));
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
panic("unlink: writei");
iput(iunlock(dp));
ip->nlink--;
iupdate(ip);
iput(iunlock(ip));
return 0;
}
// Create the path and return its unlocked inode structure.
static struct inode*
mkpath(char *path, int canexist, short type, short major, short minor)
{
uint off;
struct inode *ip, *dp;
struct uinode *ipu;
char name[DIRSIZ];
if((dp = ilock(nameiparent(path, name))) == 0)
return 0;
if(canexist && (ipu = dirlookup(dp, name, &off)) != 0){
iput(iunlock(dp));
ip = ilock(ipu);
if(ip->type != type || ip->major != major || ip->minor != minor){
iput(iunlock(ip));
return 0;
}
return ip;
}
if((ip = ilock(ialloc(dp->dev, type))) == 0){
iput(iunlock(dp));
return 0;
}
ip->major = major;
ip->minor = minor;
ip->size = 0;
ip->nlink = 1;
iupdate(ip);
if(dirlink(dp, name, ip->inum) < 0){
ip->nlink = 0;
iput(iunlock(ip));
iput(iunlock(dp));
return 0;
}
if(type == T_DIR){ // Create . and .. entries.
dp->nlink++; // for ".."
iupdate(dp);
// No ip->nlink++ for ".": avoid cyclic ref count.
if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
panic("mkpath dots");
}
iput(iunlock(dp));
return ip;
}
int
sys_open(void)
{
@ -122,30 +252,28 @@ sys_open(void)
if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
return -1;
if(omode & O_CREATE)
ip = create(path);
else
ip = namei(path);
if(ip == 0)
return -1;
if(omode & O_CREATE){
if((ip = mkpath(path, 1, T_FILE, 0, 0)) == 0)
return -1;
}else{
if((ip = ilock(namei(path))) == 0)
return -1;
if(ip->type == T_DIR && (omode & (O_RDWR|O_WRONLY))){
iput(iunlock(ip));
return -1;
}
}
if(ip->type == T_DIR && (omode & (O_RDWR|O_WRONLY))){
iput(ip);
if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){
if(f)
fileclose(f);
iput(iunlock(ip));
return -1;
}
if((f = filealloc()) == 0){
iput(ip);
return -1;
}
if((fd = fdalloc(f)) < 0){
iput(ip);
fileclose(f);
return -1;
}
iunlock(ip);
f->type = FD_FILE;
f->type = FD_INODE;
f->ip = iunlock(ip);
f->off = 0;
if(omode & O_RDWR) {
f->readable = 1;
f->writable = 1;
@ -156,8 +284,6 @@ sys_open(void)
f->readable = 1;
f->writable = 0;
}
f->ip = ip;
f->off = 0;
return fd;
}
@ -165,7 +291,7 @@ sys_open(void)
int
sys_mknod(void)
{
struct inode *nip;
struct inode *ip;
char *path;
int len;
int type, major, minor;
@ -173,14 +299,10 @@ sys_mknod(void)
if((len=argstr(0, &path)) < 0 || argint(1, &type) < 0 ||
argint(2, &major) < 0 || argint(3, &minor) < 0)
return -1;
// XXX why this check?
if(len >= DIRSIZ)
// XXX check that type == T_DEV or eliminate type arg?
if((ip = mkpath(path, 0, type, major, minor)) == 0)
return -1;
if((nip = mknod(path, type, major, minor)) == 0)
return -1;
iput(nip);
iput(iunlock(ip));
return 0;
}
@ -188,56 +310,31 @@ int
sys_mkdir(void)
{
char *path;
struct inode *ip;
if(argstr(0, &path) < 0)
if(argstr(0, &path) < 0 || (ip = mkpath(path, 0, T_DIR, 0, 0)) == 0)
return -1;
return mkdir(path);
iput(iunlock(ip));
return 0;
}
int
sys_chdir(void)
{
struct inode *ip;
char *path;
struct inode *ip;
if(argstr(0, &path) < 0)
if(argstr(0, &path) < 0 || (ip = ilock(namei(path))) == 0)
return -1;
if((ip = namei(path)) == 0)
return -1;
if(ip->type != T_DIR) {
iput(ip);
iput(iunlock(ip));
return -1;
}
iunlock(ip);
idecref(cp->cwd);
cp->cwd = ip;
iput(cp->cwd);
cp->cwd = iunlock(ip);
return 0;
}
int
sys_unlink(void)
{
char *path;
if(argstr(0, &path) < 0)
return -1;
return unlink(path);
}
int
sys_fstat(void)
{
struct file *f;
struct stat *st;
if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof *st) < 0)
return -1;
return filestat(f, st);
}
int
sys_dup(void)
{
@ -252,30 +349,18 @@ sys_dup(void)
return fd;
}
int
sys_link(void)
{
char *old, *new;
if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
return -1;
return link(old, new);
}
#define MAXARGS 20
int
sys_exec(void)
{
char *path, *argv[MAXARGS];
char *path, *argv[20];
int i;
uint uargv, uarg;
if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0)
return -1;
memset(argv, 0, sizeof argv);
memset(argv, 0, sizeof(argv));
for(i=0;; i++){
if(i >= MAXARGS)
if(i >= NELEM(argv))
return -1;
if(fetchint(cp, uargv+4*i, (int*)&uarg) < 0)
return -1;
@ -289,3 +374,26 @@ sys_exec(void)
return exec(path, argv);
}
int
sys_pipe(void)
{
int *fd;
struct file *rf, *wf;
int fd0, fd1;
if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0)
return -1;
if(pipe_alloc(&rf, &wf) < 0)
return -1;
fd0 = -1;
if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
if(fd0 >= 0)
cp->ofile[fd0] = 0;
fileclose(rf);
fileclose(wf);
return -1;
}
fd[0] = fd0;
fd[1] = fd1;
return 0;
}