/*
* linux/fs/namei.c
*
* (C) 1991 Linus Torvalds
*/
/*
* Some corrections by tytso.
*/
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <const.h>
#include <sys/stat.h>
#define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
/*
* comment out this line if you want names > NAME_LEN chars to be
* truncated. Else they will be disallowed.
*/
/* #define NO_TRUNCATE */
#define MAY_EXEC 1
#define MAY_WRITE 2
#define MAY_READ 4
/*
* permission()
*
* is used to check for read/write/execute permissions on a file.
* I don't know if we should look at just the euid or both euid and
* uid, but that should be easily changed.
*/
static int permission(struct m_inode * inode,int mask)
{
int mode = inode->i_mode;
/* special case: not even root can read/write a deleted file */
if (inode->i_dev && !inode->i_nlinks)
return 0;
else if (current->euid==inode->i_uid)
mode >>= 6;
else if (current->egid==inode->i_gid)
mode >>= 3;
if (((mode & mask & 0007) == mask) || suser())
return 1;
return 0;
}
/*
* ok, we cannot use strncmp, as the name is not in our data space.
* Thus we'll have to use match. No big problem. Match also makes
* some sanity tests.
*
* NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
*/
static int match(int len,const char * name,struct dir_entry * de)
{
register int same __asm__("ax");
if (!de || !de->inode || len > NAME_LEN)
return 0;
if (len < NAME_LEN && de->name[len])
return 0;
__asm__("cld\n\t"
"fs ; repe ; cmpsb\n\t"
"setz %%al"
:"=a" (same)
:"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
:"cx","di","si");
return same;
}
/*
* find_entry()
*
* finds an entry in the specified directory with the wanted name. It
* returns the cache buffer in which the entry was found, and the entry
* itself (as a parameter - res_dir). It does NOT read the inode of the
* entry - you'll have to do that yourself if you want to.
*
* This also takes care of the few special cases due to '..'-traversal
* over a pseudo-root and a mount point.
*/
static struct buffer_head * find_entry(struct m_inode ** dir,
const char * name, int namelen, struct dir_entry ** res_dir)
{
int entries;
int block,i;
struct buffer_head * bh;
struct dir_entry * de;
struct super_block * sb;
#ifdef NO_TRUNCATE
if (namelen > NAME_LEN)
return NULL;
#else
if (namelen > NAME_LEN)
namelen = NAME_LEN;
#endif
entries = (*dir)->i_size / (sizeof (struct dir_entry));
*res_dir = NULL;
if (!namelen)
return NULL;
/* check for '..', as we might have to do some "magic" for it */
if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
/* '..' in a pseudo-root results in a faked '.' (just change namelen) */
if ((*dir) == current->root)
namelen=1;
else if ((*dir)->i_num == ROOT_INO) {
/* '..' over a mount-point results in 'dir' being exchanged for the mounted
directory-inode. NOTE! We set mounted, so that we can iput the new dir */
sb=get_super((*dir)->i_dev);
if (sb->s_imount) {
iput(*dir);
(*dir)=sb->s_imount;
(*dir)->i_count++;
}
}
}
if (!(block = (*dir)->i_zone[0]))
return NULL;
if (!(bh = bread((*dir)->i_dev,block)))
return NULL;
i = 0;
de = (struct dir_entry *) bh->b_data;
while (i < entries) {
if ((char *)de >= BLOCK_SIZE+bh->b_data) {
brelse(bh);
bh = NULL;
if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
!(bh = bread((*dir)->i_dev,block))) {
i += DIR_ENTRIES_PER_BLOCK;
continue;
}
de = (struct dir_entry *) bh->b_data;
}
if (match(namelen,name,de)) {
*res_dir = de;
return bh;
}
de++;
i++;
}
brelse(bh);
return NULL;
}
/*
* add_entry()
*
* adds a file entry to the specified directory, using the same
* semantics as find_entry(). It returns NULL if it failed.
*
* NOTE!! The inode part of 'de' is left at 0 - which means you
* may not sleep between calling this and putting something into
* the entry, as someone else might have used it while you slept.
*/
static struct buffer_head * add_entry(struct m_inode * dir,
const char * name, int namelen, struct dir_entry ** res_dir)
{
int block,i;
struct buffer_head * bh;
struct dir_entry * de;
*res_dir = NULL;
#ifdef NO_TRUNCATE
if (namelen > NAME_LEN)
return NULL;
#else
if (namelen > NAME_LEN)
namelen = NAME_LEN;
#endif
if (!namelen)
return NULL;
if (!(block = dir->i_zone[0]))
return NULL;
if (!(bh = bread(dir->i_dev,block)))
return NULL;
i = 0;
de = (struct dir_entry *) bh->b_data;
while (1) {
if ((char *)de >= BLOCK_SIZE+bh->b_data) {
brelse(bh);
bh = NULL;
block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
if (!block)
return NULL;
if (!(bh = bread(dir->i_dev,block))) {
i += DIR_ENTRIES_PER_BLOCK;
continue;
}
de = (struct dir_entry *) bh->b_data;
}
if (i*sizeof(struct dir_entry) >= dir->i_size) {
de->inode=0;
dir->i_size = (i+1)*sizeof(struct dir_entry);
dir->i_dirt = 1;
dir->i_ctime = CURRENT_TIME;
}
if (!de->inode) {
dir->i_mtime = CURRENT_TIME;
for (i=0; i < NAME_LEN ; i++)
de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
bh->b_dirt = 1;
*res_dir = de;
return bh;
}
de++;
i++;
}
brelse(bh);
return NULL;
}
/*
* get_dir()
*
* Getdir traverses the pathname until it hits the topmost directory.
* It returns NULL on failure.
*/
static struct m_inode * get_dir(const char * pathname)
{
char c;
const char * thisname;
struct m_inode * inode;
struct buffer_head * bh;
int namelen,inr,idev;
struct dir_entry * de;
if (!current->root || !current->root->i_count)
panic("No root inode");
if (!current->pwd || !current->pwd->i_count)
panic("No cwd inode");
if ((c=get_fs_byte(pathname))=='/') {
inode = current->root;
pathname++;
} else if (c)
inode = current->pwd;
else
return NULL; /* empty name is bad */
inode->i_count++;
while (1) {
thisname = pathname;
if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
iput(inode);
return NULL;
}
for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
/* nothing */ ;
if (!c)
return inode;
if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
iput(inode);
return NULL;
}
inr = de->inode;
idev = inode->i_dev;
brelse(bh);
iput(inode);
if (!(inode = iget(idev,inr)))
return NULL;
}
}
/*
* dir_namei()
*
* dir_namei() returns the inode of the directory of the
* specified name, and the name within that directory.
*/
static struct m_inode * dir_namei(const char * pathname,
int * namelen, const char ** name)
{
char c;
const char * basename;
struct m_inode * dir;
if (!(dir = get_dir(pathname)))
return NULL;
basename = pathname;
while (c=get_fs_byte(pathname++))
if (c=='/')
basename=pathname;
*namelen = pathname-basename-1;
*name = basename;
return dir;
}
/*
* namei()
*
* is used by most simple commands to get the inode of a specified name.
* Open, link etc use their own routines, but this is enough for things
* like 'chmod' etc.
*/
struct m_inode * namei(const char * pathname)
{
const char * basename;
int inr,dev,namelen;
struct m_inode * dir;
struct buffer_head * bh;
struct dir_entry * de;
if (!(dir = dir_namei(pathname,&namelen,&basename)))
return NULL;
if (!namelen) /* special case: '/usr/' etc */
return dir;
bh = find_entry(&dir,basename,namelen,&de);
if (!bh) {
iput(dir);
return NULL;
}
inr = de->inode;
dev = dir->i_dev;
brelse(bh);
iput(dir);
dir=iget(dev,inr);
if (dir) {
dir->i_atime=CURRENT_TIME;
dir->i_dirt=1;
}
return dir;
}
/*
* open_namei()
*
* namei for open - this is in fact almost the whole open-routine.
*/
int open_namei(const char * pathname, int flag, int mode,
struct m_inode ** res_inode)
{
const char * basename;
int inr,dev,namelen;
struct m_inode * dir, *inode;
struct buffer_head * bh;
struct dir_entry * de;
if ((flag & O_TRUNC) && !(flag & O_
没有合适的资源?快使用搜索试试~ 我知道了~
Linux-0.11内核源码
共132个文件
c:51个
h:33个
ipch:19个
需积分: 0 0 下载量 116 浏览量
2023-06-20
16:51:01
上传
评论 2
收藏 6.47MB ZIP 举报
温馨提示
Linux 0.11 内核是 Linux 内核的一个早期版本,于 1991 年发布。它是由 Linus Torvalds 编写的,是一个基于 UNIX 的操作系统内核。Linux 0.11 内核源码包含了操作系统内核的核心代码和一些驱动程序。该内核的开发和维护过程采用开源开发模式,因此它的源代码被广泛地研究和修改。Linux 0.11 内核被广泛地应用于嵌入式设备、服务器和个人计算机等领域。 该内核的源代码包含了文件系统、进程管理、内存管理、网络协议等多个子系统。它的设计理念是模块化,允许开发者扩展和替换不同的部分。Linux 0.11 内核具有很高的可移植性和可扩展性,可以运行在多个硬件平台上,并且可以被定制以适应不同的应用场景。 虽然 Linux 0.11 内核已经经历了多次更新和升级,但它的源代码仍然被视为学习 Unix/Linux 内核的入门级别材料,更是从中汲取 Unix/Linux 内核设计的经验和智慧的重要方式。
资源推荐
资源详情
资源评论
收起资源包目录
Linux-0.11内核源码 (132个子文件)
namei.c 16KB
console.c 14KB
floppy.c 11KB
memory.c 11KB
exec.c 9KB
buffer.c 9KB
sched.c 8KB
hd.c 8KB
tty_io.c 7KB
malloc.c 7KB
inode.c 7KB
super.c 5KB
main.c 5KB
tty_ioctl.c 5KB
traps.c 5KB
vsprintf.c 5KB
build.c 4KB
open.c 4KB
exit.c 4KB
bitmap.c 4KB
sys.c 4KB
fork.c 4KB
ll_rw_blk.c 3KB
read_write.c 3KB
ramdisk.c 3KB
signal.c 3KB
pipe.c 2KB
char_dev.c 2KB
file_dev.c 2KB
mktime.c 1KB
fcntl.c 1KB
block_dev.c 1KB
serial.c 1KB
ctype.c 1KB
stat.c 1KB
truncate.c 1KB
math_emulate.c 1023B
ioctl.c 977B
printk.c 734B
panic.c 448B
open.c 389B
wait.c 253B
_exit.c 198B
string.c 177B
execve.c 170B
write.c 160B
close.c 131B
setsid.c 128B
dup.c 127B
file_table.c 122B
errno.c 73B
Browse.VC.db 2.03MB
string.h 8KB
unistd.h 6KB
a.out.h 6KB
sched.h 6KB
fs.h 5KB
termios.h 5KB
blk.h 3KB
sys.h 3KB
fdreg.h 2KB
tty.h 2KB
hdreg.h 2KB
signal.h 2KB
system.h 2KB
fcntl.h 1KB
segment.h 1KB
stat.h 1KB
config.h 1KB
errno.h 1KB
ctype.h 1KB
types.h 805B
stdarg.h 780B
kernel.h 734B
time.h 734B
wait.h 560B
memory.h 507B
io.h 477B
const.h 321B
head.h 304B
stddef.h 286B
utsname.h 234B
utime.h 225B
mm.h 219B
times.h 200B
linux-0.11.iml 335B
OPEN.ipch 2MB
NAMEI.ipch 1.88MB
TRAPS.ipch 1.81MB
IOCTL.ipch 1.81MB
INODE.ipch 1.81MB
TTY_IO.ipch 1.75MB
MAIN.ipch 1.63MB
SCHED.ipch 1.56MB
CONSOLE.ipch 1.56MB
READ_WRITE.ipch 1.56MB
LL_RW_BLK.ipch 1.5MB
SUPER.ipch 1.5MB
FORK.ipch 1.5MB
BLOCK_DEV.ipch 1.5MB
共 132 条
- 1
- 2
资源评论
赛博二哈
- 粉丝: 3802
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功