You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
linux/stat.c

185 lines
4.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* linux/fs/stat.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <fcntl.h>
static void cp_stat(struct m_inode * inode, struct stat * statbuf)
{
struct stat tmp;
int i;
verify_area(statbuf,sizeof (* statbuf));
tmp.st_dev = inode->i_dev;
tmp.st_ino = inode->i_num;
tmp.st_mode = inode->i_mode;
tmp.st_nlink = inode->i_nlinks;
tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_zone[0];
tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
for (i=0 ; i<sizeof (tmp) ; i++)
put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
}
static void new_cp_stat(struct m_inode * inode, struct stat * statbuf)
{
struct stat tmp;
int i;
verify_area(statbuf,sizeof (* statbuf));
tmp.st_dev = inode->i_dev;
tmp.st_ino = inode->i_num;
tmp.st_mode = inode->i_mode;
tmp.st_nlink = inode->i_nlinks;
tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_zone[0];
tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
for (i=0 ; i<sizeof (tmp) ; i++)
//put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
((char *)statbuf)[i]=((char *) &tmp)[i];
}
int sys_stat(char * filename, struct stat * statbuf)
{
struct m_inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
cp_stat(inode,statbuf);
iput(inode);
return 0;
}
int my_stat(char * filename, struct stat * statbuf)
{
struct m_inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
new_cp_stat(inode,statbuf);
iput(inode);
return 0;
}
int sys_lstat(char * filename, struct stat * statbuf)
{
return sys_stat(filename, statbuf);
}
int sys_fstat(unsigned int fd, struct stat * statbuf)
{
struct file * f;
struct m_inode * inode;
if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
return -EBADF;
cp_stat(inode,statbuf);
return 0;
}
int sys_readlink()
{
return -ENOSYS;
}
char *sys_getcwd(char *buf,size_t size)
{
char path[128], cwd[128], name[16], res[128];
int dirp;
struct stat sb, sb_d, sb_1;
dev_t dev;
ino_t ino;
int tmp = 0, i;
memset(res, 0, sizeof(res));
while(1)
{
//将当前目录的字符串"."存入buf中才能作为stat的参数传入使用
put_fs_byte('.', &buf[0]);
put_fs_byte(0, &buf[1]);
//获取当前目录的文件信息
my_stat(buf, &sb);
dev = sb.st_dev;
ino = sb.st_ino;
//将父目录".."字符串写入buf中
put_fs_byte('.', &buf[0]);
put_fs_byte('.', &buf[1]);
put_fs_byte(0, &buf[2]);
//获取父目录的对应的目录流
dirp = sys_open(buf, O_RDONLY, 0);
//获取父目录的文件信息
my_stat(buf, &sb_1);
//判断当前目录是否与父目录相同,相同则找到当前路径
if(sb_1.st_dev == dev && sb_1.st_ino == ino)
{
break;
}
//在父目录对应的目录流读取条目与getdents类似
//遍历父目录下对应的所有目录与之前获取的当前目录想匹配,匹配成功的目录项对当前目录所在的目录项,即可保存名字后继续向前寻找
while(my_read(dirp, name, 16) > 0 && name[0])
{
tmp = 0;
memset(path, 0, sizeof(path));
path[0] = '.';path[1] = '.';path[2] = '/';
while(name[tmp+2])
{
path[tmp+3] = name[tmp+2];
tmp++;
}
path[tmp+3] = 0;
for(i=0;i<size;i++)
put_fs_byte(path[i], &buf[i]);
//获取当前父目录下的目录项文件信息
my_stat(buf, &sb_d);
if(dev == sb_d.st_dev && ino == sb_d.st_ino)
{
//若匹配成功,则写入文件路径
memset(cwd, 0, sizeof(cwd));
strcat(cwd, "/");
strcat(cwd, name+2);
strcat(cwd, res);
strncpy(res, cwd, size);
break;
}
}
//关闭当前打开的父目录
sys_close(dirp);
//将buf重新修改为父目录对应的字符串".."
put_fs_byte('.', &buf[0]);
put_fs_byte('.', &buf[1]);
put_fs_byte(0, &buf[2]);
//改变当前目录到上一级,继续上述遍历寻找步骤直到父目录与当前目录相一致
sys_chdir(buf);
}
//将得到的路径写入buf中
for(i=0;i<size;i++)
put_fs_byte(res[i], &buf[i]);
sys_close(dirp);
sys_chdir(buf);
return buf;
}