|
|
/*
|
|
|
* 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;
|
|
|
} |