📄 dfs.c
字号:
//
// dfs.c
//
// Disk filesystem routines
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include <os/krnl.h>
struct fsops dfsops =
{
FSOP_READ | FSOP_WRITE | FSOP_IOCTL | FSOP_TELL | FSOP_LSEEK | FSOP_FTRUNCATE |
FSOP_FUTIME | FSOP_FSTAT,
NULL,
NULL,
dfs_mkfs,
dfs_mount,
dfs_umount,
dfs_statfs,
dfs_open,
dfs_close,
dfs_destroy,
dfs_fsync,
dfs_read,
dfs_write,
dfs_ioctl,
dfs_tell,
dfs_lseek,
dfs_ftruncate,
dfs_futime,
dfs_utime,
dfs_fstat,
dfs_stat,
dfs_access,
dfs_fchmod,
dfs_chmod,
dfs_fchown,
dfs_chown,
dfs_mkdir,
dfs_rmdir,
dfs_rename,
dfs_link,
dfs_unlink,
dfs_opendir,
dfs_readdir
};
void init_dfs()
{
register_filesystem("dfs", &dfsops);
}
int dfs_utime(struct fs *fs, char *name, struct utimbuf *times)
{
struct inode *inode;
int rc;
rc = namei((struct filsys *) fs->data, name, &inode);
if (rc < 0) return rc;
rc = checki(inode, S_IWRITE);
if (rc < 0)
{
release_inode(inode);
return rc;
}
if (times->ctime != -1) inode->desc->ctime = times->ctime;
if (times->modtime != -1) inode->desc->mtime = times->modtime;
mark_inode_dirty(inode);
release_inode(inode);
return 0;
}
int dfs_stat(struct fs *fs, char *name, struct stat64 *buffer)
{
struct inode *inode;
off64_t size;
int rc;
rc = namei((struct filsys *) fs->data, name, &inode);
if (rc < 0) return rc;
size = inode->desc->size;
if (buffer)
{
memset(buffer, 0, sizeof(struct stat64));
buffer->st_mode = inode->desc->mode;
buffer->st_uid = inode->desc->uid;
buffer->st_gid = inode->desc->gid;
buffer->st_ino = inode->ino;
buffer->st_nlink = inode->desc->linkcount;
buffer->st_dev = ((struct filsys *) fs->data)->devno;
buffer->st_atime = time(NULL);
buffer->st_mtime = inode->desc->mtime;
buffer->st_ctime = inode->desc->ctime;
buffer->st_size = inode->desc->size;
}
release_inode(inode);
return (int) size;
}
int dfs_access(struct fs *fs, char *name, int mode)
{
struct thread *thread = self();
struct inode *inode;
int rc;
rc = namei((struct filsys *) fs->data, name, &inode);
if (rc < 0) return rc;
if (mode != 0 && thread->euid != 0)
{
if (thread->euid != inode->desc->uid)
{
mode >>= 3;
if (thread->egid != inode->desc->gid) mode >>= 3;
}
if ((mode & inode->desc->mode) == 0) rc = -EACCES;
}
release_inode(inode);
return rc;
}
int dfs_mkdir(struct fs *fs, char *name, int mode)
{
struct inode *parent;
ino_t ino;
struct inode *dir;
int len;
int rc;
len = strlen(name);
rc = diri((struct filsys *) fs->data, &name, &len, &parent);
if (rc < 0) return rc;
rc = find_dir_entry(parent, name, len, &ino);
if (rc != -ENOENT)
{
release_inode(parent);
return rc >= 0 ? -EEXIST : rc;
}
dir = alloc_inode(parent, mode);
if (!dir)
{
release_inode(parent);
return -ENOSPC;
}
dir->desc->mode = S_IFDIR | (mode & S_IRWXUGO);
dir->desc->linkcount++;
mark_inode_dirty(dir);
rc = add_dir_entry(parent, name, len, dir->ino);
if (rc < 0)
{
unlink_inode(dir);
release_inode(dir);
release_inode(parent);
return rc;
}
release_inode(dir);
release_inode(parent);
return 0;
}
int dfs_rmdir(struct fs *fs, char *name)
{
struct inode *parent;
struct inode *dir;
ino_t ino;
int len;
int rc;
len = strlen(name);
rc = diri((struct filsys *) fs->data, &name, &len, &parent);
if (rc < 0) return rc;
rc = find_dir_entry(parent, name, len, &ino);
if (rc < 0)
{
release_inode(parent);
return rc;
}
if (ino == DFS_INODE_ROOT)
{
release_inode(parent);
return -EPERM;
}
rc = get_inode(parent->fs, ino, &dir);
if (rc < 0)
{
release_inode(parent);
return rc;
}
if (!S_ISDIR(dir->desc->mode))
{
release_inode(dir);
release_inode(parent);
return -ENOTDIR;
}
if (dir->desc->size > 0)
{
release_inode(dir);
release_inode(parent);
return -ENOTEMPTY;
}
rc = delete_dir_entry(parent, name, len);
if (rc < 0)
{
release_inode(dir);
release_inode(parent);
return rc;
}
rc = unlink_inode(dir);
if (rc < 0)
{
release_inode(dir);
release_inode(parent);
return rc;
}
release_inode(dir);
release_inode(parent);
return 0;
}
int dfs_rename(struct fs *fs, char *oldname, char *newname)
{
struct inode *oldparent;
struct inode *newparent;
int oldlen;
int newlen;
ino_t ino;
int rc;
oldlen = strlen(oldname);
rc = diri((struct filsys *) fs->data, &oldname, &oldlen, &oldparent);
if (rc < 0) return rc;
rc = find_dir_entry(oldparent, oldname, oldlen, &ino);
if (rc < 0)
{
release_inode(oldparent);
return rc;
}
newlen = strlen(newname);
rc = diri((struct filsys *) fs->data, &newname, &newlen, &newparent);
if (rc < 0)
{
release_inode(oldparent);
return rc;
}
rc = find_dir_entry(newparent, newname, newlen, NULL);
if (rc != -ENOENT)
{
release_inode(oldparent);
release_inode(newparent);
if (strcmp(oldname, newname) == 0) return 0;
return rc >= 0 ? -EEXIST : rc;
}
if (checki(oldparent, S_IWRITE) < 0 || checki(newparent, S_IWRITE) < 0)
{
release_inode(oldparent);
release_inode(newparent);
return -EACCES;
}
rc = add_dir_entry(newparent, newname, newlen, ino);
if (rc < 0)
{
release_inode(oldparent);
release_inode(newparent);
return rc;
}
rc = delete_dir_entry(oldparent, oldname, oldlen);
if (rc < 0)
{
release_inode(oldparent);
release_inode(newparent);
return rc;
}
release_inode(oldparent);
release_inode(newparent);
return 0;
}
int dfs_link(struct fs *fs, char *oldname, char *newname)
{
struct inode *inode;
struct inode *parent;
int len;
int rc;
rc = namei((struct filsys *) fs->data, oldname, &inode);
if (rc < 0) return rc;
len = strlen(newname);
rc = diri((struct filsys *) fs->data, &newname, &len, &parent);
if (rc < 0)
{
release_inode(inode);
return rc;
}
rc = find_dir_entry(parent, newname, len, NULL);
if (rc != -ENOENT)
{
release_inode(inode);
release_inode(parent);
return rc >= 0 ? -EEXIST : rc;
}
inode->desc->linkcount++;
mark_inode_dirty(inode);
rc = add_dir_entry(parent, newname, len, inode->ino);
if (rc < 0)
{
unlink_inode(inode);
release_inode(inode);
release_inode(parent);
return rc;
}
release_inode(inode);
release_inode(parent);
return 0;
}
int dfs_unlink(struct fs *fs, char *name)
{
struct inode *dir;
struct inode *inode;
ino_t ino;
int len;
int rc;
len = strlen(name);
rc = diri((struct filsys *) fs->data, &name, &len, &dir);
if (rc < 0) return rc;
rc = find_dir_entry(dir, name, len, &ino);
if (rc < 0)
{
release_inode(dir);
return rc;
}
rc = get_inode(dir->fs, ino, &inode);
if (rc < 0)
{
release_inode(dir);
return rc;
}
if (S_ISDIR(inode->desc->mode))
{
release_inode(inode);
release_inode(dir);
return -EISDIR;
}
rc = delete_dir_entry(dir, name, len);
if (rc < 0)
{
release_inode(inode);
release_inode(dir);
return rc;
}
rc = unlink_inode(inode);
if (rc < 0)
{
release_inode(inode);
release_inode(dir);
return rc;
}
release_inode(inode);
release_inode(dir);
return 0;
}
int dfs_chmod(struct fs *fs, char *name, int mode)
{
struct thread *thread = self();
struct inode *inode;
int rc;
rc = namei((struct filsys *) fs->data, name, &inode);
if (rc < 0) return rc;
if (thread->euid != 0 && thread->euid != inode->desc->uid)
{
release_inode(inode);
return -EPERM;
}
inode->desc->mode = (inode->desc->mode & ~S_IRWXUGO) | (mode & S_IRWXUGO);
mark_inode_dirty(inode);
release_inode(inode);
return 0;
}
int dfs_chown(struct fs *fs, char *name, int owner, int group)
{
struct thread *thread = self();
struct inode *inode;
int rc;
rc = namei((struct filsys *) fs->data, name, &inode);
if (rc < 0) return rc;
if (thread->euid != 0)
{
release_inode(inode);
return -EPERM;
}
if (owner != -1) inode->desc->uid = owner;
if (group != -1) inode->desc->gid = group;
mark_inode_dirty(inode);
release_inode(inode);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -