📄 fatdriver.cpp
字号:
if(!_fv->chdir(parent))
{
void *buf;
uint size;
char **names;
uint n;
if(buf = _fv->read_file(child,size))
{
if(names = fetch_long_names(buf,size,n))
{
__ret = curr_proc->_f.opendir(names,n);
for(int i=0;i<n;i++) delete names[i];
delete names;
}
delete buf;
}
}
RESTORE_ROOT(r);
pwd = cwd;
}
bsem.up();
return (DIR*)__ret;
}
dirent* FATdriver::readdir(DIR* d_fd)
{
return curr_proc->_f.readdir(d_fd);
}
int FATdriver::closedir(DIR* d_fd)
{
return curr_proc->_f.closedir(d_fd);
}
void FATdriver::rewinddir(DIR* d_fd)
{
curr_proc->_f.rewinddir(d_fd);
}
int FATdriver::open(char* path,int access,mode_t perm)
{
bsem.down();
int __ret = -1;
FATvolume *_fv;
void *buf;
uint size;
if(_fv = get_FATvolume(path))
{
fdir cwd = pwd;
fdir r,dir;
int opened = 0;
int newly_created = 0;
char nchild[255],rchild[255];
char parent[1024],child[255];
split_path(path,parent,child);
strcpy(nchild,child);
strcpy(rchild,child);
SAVE_ROOT(r);
if(!_fv->chdir(parent))
if(!_fv->get_short_dir_entry(child,dir))
{
if((access & O_CREAT) && (access & O_EXCL))
{
pwd = cwd;
RESTORE_ROOT(r);
bsem.up();
return __ret;
}
}
else
{
if(access & O_CREAT)
{
newly_created = 1;
_fv->put_dir_entry(child,ATTR_ARCHIVE,0);
}
else
{
pwd = cwd;
RESTORE_ROOT(r);
bsem.up();
return __ret;
}
}
if(is_open(_fv->get_drive(),dir)) opened = 1;
if(newly_created)
_fv->get_short_dir_entry(nchild,dir);
if(!opened)
if(!(buf = _fv->read_file(rchild,size)))
{
pwd = cwd;
RESTORE_ROOT(r);
bsem.up();
return -1;
}
int fi,fti;
if((fi = curr_proc->_f.get_fi()) >= 0)
if((fti = get_fti()) >= 0)
{
FILE_tab[fti].p_finode = get_finode(_fv->get_drive(),dir);
FILE_tab[fti].rw_ptr = 0;
if(access & O_APPEND)
FILE_tab[fti].rw_ptr = (opened) ? FILE_tab[fti].p_finode->size:size;
if(access & O_TRUNC) FILE_tab[fti].rw_ptr = 0;
FILE_tab[fti].mode = access;
FILE_tab[fti].fd = fi;
FILE_tab[fti].rc++;
FILE_tab[fti].p_finode->rc++;
if(!opened)
{
FILE_tab[fti].p_finode->buf = buf;
FILE_tab[fti].p_finode->size = size;
FILE_tab[fti].p_finode->dir = dir;
}
curr_proc->_f.fd[fi] = &FILE_tab[fti];
curr_proc->_f.fcount++;
}
pwd = cwd;
RESTORE_ROOT(r);
__ret = fi;
}
bsem.up();
return __ret;
}
void* FATdriver::open_init(char *path)
{
bsem.down();
void *__ret = NULL;
FATvolume *_fv;
if(_fv = get_FATvolume(path))
{
fdir cwd = pwd,r;
uint size;
SAVE_ROOT(r);
char parent[1024],child[255];
split_path(path,parent,child);
if(!_fv->chdir(parent))
__ret = _fv->read_file(child,size);
RESTORE_ROOT(r);
pwd = cwd;
}
bsem.up();
return __ret;
}
int FATdriver::creat(char* path,int mode)
{
return open(path,O_WRONLY|O_CREAT|O_TRUNC,mode);
}
ssize_t FATdriver::read(int fdesc,void *buf,size_t size)
{
int rw_ptr = curr_proc->_f.fd[fdesc]->rw_ptr;
if(rw_ptr + size > curr_proc->_f.fd[fdesc]->p_finode->size)
size = curr_proc->_f.fd[fdesc]->p_finode->size - rw_ptr;
if(!size) return 0;
if((curr_proc->_f.fd[fdesc]->mode & O_RDONLY)||(curr_proc->_f.fd[fdesc]->mode & O_RDWR))
{
void *src = (byte*)curr_proc->_f.fd[fdesc]->p_finode->buf+rw_ptr;
memcpy(buf,src,size);
curr_proc->_f.fd[fdesc]->rw_ptr += size;
return size;
}
return -1;
}
ssize_t FATdriver::write(int fdesc,void* buf,size_t size)
{
bsem.down();
int rw_ptr = curr_proc->_f.fd[fdesc]->rw_ptr;
if(rw_ptr + size > curr_proc->_f.fd[fdesc]->p_finode->size)
size = curr_proc->_f.fd[fdesc]->p_finode->size - rw_ptr;
if(!size)
{
bsem.up();
return 0;
}
if((curr_proc->_f.fd[fdesc]->mode & O_WRONLY)||(curr_proc->_f.fd[fdesc]->mode & O_RDWR))
{
void *dst = (byte*)curr_proc->_f.fd[fdesc]->p_finode->buf+rw_ptr;
memcpy(dst,buf,size);
curr_proc->_f.fd[fdesc]->rw_ptr += size;
bsem.up();
return size;
}
bsem.up();
return -1;
}
int FATdriver::close(int fdesc)
{
FILE *fp = curr_proc->_f.fd[fdesc];
if(!fp) return -1;
fp->fd = 0;
fp->rc--;
fp->rw_ptr = 0;
fp->p_finode->rc--;
/*if rc = 0 we have to write the file back to disk if it is opened in write mode*/
if(fp->p_finode->rc == 0)
{
if(fp->mode == O_WRONLY)
{
cout<<"file will be written\n";
getch();
bsem.down();
FATvolume *_fv;
if(_fv = get_FATvolume(fp->p_finode->drive))
{
uint start = _fv->get_start_clus(&fp->p_finode->dir);
if(_fv->write_clus_chain(start,fp->p_finode->buf,fp->p_finode->size)<0)
{
bsem.up();
return -1;
}
bsem.up();
}
}
fp->p_finode->size = 0;
delete fp->p_finode->buf;
}
curr_proc->_f.fd[fdesc] = NULL;
curr_proc->_f.fcount--;
return 0;
}
off_t FATdriver::lseek(int fdesc,int pos,int whence)
{
/* if pos exceeds EOF, the file should be expanded */
uint end = curr_proc->_f.fd[fdesc]->p_finode->size;
switch(whence)
{
case SEEK_CUR:curr_proc->_f.fd[fdesc]->rw_ptr += pos;break;
case SEEK_SET:curr_proc->_f.fd[fdesc]->rw_ptr = 0 + pos;break;
case SEEK_END:curr_proc->_f.fd[fdesc]->rw_ptr = end+pos;break;
}
return curr_proc->_f.fd[fdesc]->rw_ptr;
}
finode* FATdriver::get_finode(char drive,fdir &dir)
{
for(int i=0;i<SYS_FILE_OPENMAX;i++)
if(FAT_inode[i].drive == drive && is_equal(FAT_inode[i].dir,dir))
return &FAT_inode[i];
for(int i=0;i<SYS_FILE_OPENMAX;i++)
{
if(FAT_inode[i].rc == 0) return &FAT_inode[i];
}
return NULL;
}
int FATdriver::is_open(char drive,fdir &dir)
{
for(int i=0;i<SYS_FILE_OPENMAX;i++)
if(FAT_inode[i].drive == drive && is_equal(FAT_inode[i].dir,dir))
return 1;
return 0;
}
char** FATdriver::fetch_long_names(void *buf,uint size,uint &n)
{
/*
*This function should fetch long names. currently i have implemented to fetch short
*names only
*/
fdir *dir = (fdir*)buf;
int i = 0;
n = 0;
char **ret;
uint processed = 0;
while(dir[i].dir_name[0] != 0x00 && processed < size)
{
if(dir[i].dir_name[0] != 0xE5 && dir[i].dir_attr != ATTR_LONG_NAME)
{
n++;
}
i++;
processed += 32;
}
ret = new char*[n];
for(i=0;i<n;i++)
ret[i] = new char[13];
i=0;n=0;processed = 0;
while(dir[i].dir_name[0] != 0x00 && processed < size)
{
if(dir[i].dir_name[0] != 0xE5 && dir[i].dir_attr != ATTR_LONG_NAME)
{
strncpy(ret[n],(char*)dir[i].dir_name,11);
ret[n][11] = '\0';
n++;
}
i++;
processed += 32;
}
return ret;
}
void FATdriver::split_path(char *path,char *parent,char *child)
{
if(path[1] == ':') path = path + 2;
int len = strlen(path);
int j,flag = 0;
for(int i=0;i<len;i++)
{
if(path[i] == '\\')
{
j = i;
flag = 1;
}
}
if(!flag)
{
strcpy(parent,"");
strcpy(child,path);
}
else
{
if(!j)
{
strncpy(parent,path,j+1);
parent[j+1]='\0';
}
else
{
strncpy(parent,path,j);
parent[j]='\0';
}
strcpy(child,path+j+1);
}
}
int FATdriver::get_fti()
{
for(int i=0;i<SYS_FILE_OPENMAX;i++)
if(FILE_tab[i].rc == 0)
return i;
return -1;
}
FATdriver _FAT_driver;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -