📄 cdfs.c
字号:
vd = (struct iso_volume_descriptor *) buf->data;
cdfs->volblks = isonum_733(vd->volume_space_size);
rc = cdfs_read_path_table(cdfs, vd);
if (rc < 0) return rc;
release_buffer(cdfs->cache, buf);
// Device mounted successfully
fs->data = cdfs;
return 0;
}
int cdfs_umount(struct fs *fs)
{
struct cdfs *cdfs = (struct cdfs *) fs->data;
// Free cache
if (cdfs->cache) free_buffer_pool(cdfs->cache);
// Close device
dev_close(cdfs->devno);
// Deallocate file system
if (cdfs->path_table_buffer) kfree(cdfs->path_table_buffer);
if (cdfs->path_table) kfree(cdfs->path_table);
kfree(cdfs);
return 0;
}
int cdfs_statfs(struct fs *fs, struct statfs *buf)
{
struct cdfs *cdfs = (struct cdfs *) fs->data;
buf->bsize = CDFS_BLOCKSIZE;
buf->iosize = CDFS_BLOCKSIZE;
buf->blocks = cdfs->volblks;
buf->bfree = 0;
buf->files = -1;
buf->ffree = 0;
buf->cachesize = cdfs->cache->poolsize * CDFS_BLOCKSIZE;
return 0;
}
int cdfs_open(struct file *filp, char *name)
{
struct cdfs *cdfs = (struct cdfs *) filp->fs->data;
struct iso_directory_record *rec;
struct cdfs_file *cdfile;
struct buf *buf;
time_t date;
int size;
int extent;
int flags;
int rc;
// Check open mode
if (filp->flags & (O_CREAT | O_TRUNC | O_APPEND)) return -EROFS;
// Locate file in file system
rc = cdfs_find_file(cdfs, name, strlen(name), &buf, &rec);
if (rc < 0) return rc;
flags = isonum_711(rec->flags);
extent = isonum_733(rec->extent);
date = cdfs_isodate(rec->date);
size = isonum_733(rec->size);
release_buffer(cdfs->cache, buf);
// Allocate and initialize file block
cdfile = (struct cdfs_file *) kmalloc(sizeof(struct cdfs_file));
if (!cdfile) return -ENOMEM;
cdfile->extent = extent;
cdfile->date = date;
cdfile->size = size;
if (flags & 2) filp->flags |= F_DIR;
filp->data = cdfile;
filp->mode = S_IFREG | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;;
return 0;
}
int cdfs_close(struct file *filp)
{
struct cdfs_file *cdfile = (struct cdfs_file *) filp->data;
if (cdfile) kfree(cdfile);
return 0;
}
int cdfs_fsync(struct file *filp)
{
return 0;
}
int cdfs_read(struct file *filp, void *data, size_t size, off64_t pos)
{
struct cdfs_file *cdfile = (struct cdfs_file *) filp->data;
struct cdfs *cdfs = (struct cdfs *) filp->fs->data;
size_t read;
size_t count;
size_t left;
char *p;
int iblock;
int start;
int blk;
struct buf *buf;
read = 0;
p = (char *) data;
while (pos < cdfile->size && size > 0)
{
iblock = (int) pos / CDFS_BLOCKSIZE;
start = (int) pos % CDFS_BLOCKSIZE;
count = CDFS_BLOCKSIZE - start;
if (count > size) count = size;
left = cdfile->size - (int) pos;
if (count > left) count = left;
if (count <= 0) break;
blk = cdfile->extent + iblock;
if (filp->flags & O_DIRECT)
{
if (start != 0 || count != CDFS_BLOCKSIZE) return read;
if (dev_read(cdfs->devno, p, count, blk, 0) != (int) count) return read;
}
else
{
buf = get_buffer(cdfs->cache, blk);
if (!buf) return -EIO;
memcpy(p, buf->data + start, count);
release_buffer(cdfs->cache, buf);
}
pos += count;
p += count;
read += count;
size -= count;
}
return read;
}
off64_t cdfs_tell(struct file *filp)
{
return filp->pos;
}
off64_t cdfs_lseek(struct file *filp, off64_t offset, int origin)
{
struct cdfs_file *cdfile = (struct cdfs_file *) filp->data;
switch (origin)
{
case SEEK_END:
offset += cdfile->size;
break;
case SEEK_CUR:
offset += filp->pos;
}
if (offset < 0) return -EINVAL;
filp->pos = offset;
return offset;
}
int cdfs_fstat(struct file *filp, struct stat64 *buffer)
{
struct cdfs_file *cdfile = (struct cdfs_file *) filp->data;
struct cdfs *cdfs = (struct cdfs *) filp->fs->data;
if (buffer)
{
memset(buffer, 0, sizeof(struct stat64));
if (filp->flags & F_DIR)
buffer->st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
else
buffer->st_mode = S_IFREG | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
buffer->st_ino = cdfile->extent;
buffer->st_nlink = 1;
buffer->st_dev = cdfs->devno;
buffer->st_atime = buffer->st_mtime = buffer->st_ctime = cdfile->date;
buffer->st_size = cdfile->size;
}
return cdfile->size;
}
int cdfs_stat(struct fs *fs, char *name, struct stat64 *buffer)
{
struct cdfs *cdfs = (struct cdfs *) fs->data;
struct iso_directory_record *rec;
struct buf *buf;
int rc;
int size;
rc = cdfs_find_file(cdfs, name, strlen(name), &buf, &rec);
if (rc < 0) return rc;
size = isonum_733(rec->size);
if (buffer)
{
memset(buffer, 0, sizeof(struct stat64));
if (rec->flags[0] & 2)
buffer->st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
else
buffer->st_mode = S_IFREG | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
buffer->st_ino = isonum_733(rec->extent);
buffer->st_nlink = 1;
buffer->st_dev = cdfs->devno;
buffer->st_atime = buffer->st_mtime = buffer->st_ctime = cdfs_isodate(rec->date);
buffer->st_size = size;
};
release_buffer(cdfs->cache, buf);
return size;
}
int cdfs_opendir(struct file *filp, char *name)
{
struct cdfs *cdfs = (struct cdfs *) filp->fs->data;
struct iso_directory_record *rec;
struct cdfs_file *cdfile;
struct buf *buf;
time_t date;
int size;
int extent;
int flags;
int rc;
// Locate directory
rc = cdfs_find_file(cdfs, name, strlen(name), &buf, &rec);
if (rc < 0) return rc;
flags = isonum_711(rec->flags);
extent = isonum_733(rec->extent);
date = cdfs_isodate(rec->date);
size = isonum_733(rec->size);
release_buffer(cdfs->cache, buf);
if (!(flags & 2)) return -ENOTDIR;
// Allocate and initialize file block
cdfile = (struct cdfs_file *) kmalloc(sizeof(struct cdfs_file));
if (!cdfile) return -ENOMEM;
cdfile->extent = extent;
cdfile->date = date;
cdfile->size = size;
filp->data = cdfile;
filp->mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
return 0;
}
int cdfs_readdir(struct file *filp, struct direntry *dirp, int count)
{
struct cdfs_file *cdfile = (struct cdfs_file *) filp->data;
struct cdfs *cdfs = (struct cdfs *) filp->fs->data;
struct iso_directory_record *rec;
struct buf *buf;
int namelen;
int reclen;
char *name;
wchar_t *wname;
blkagain:
if (count != 1) return -EINVAL;
if (filp->pos >= cdfile->size) return 0;
// Get directory block
buf = get_buffer(cdfs->cache, cdfile->extent + (int) filp->pos / CDFS_BLOCKSIZE);
if (!buf) return -EIO;
// Locate directory record
recagain:
rec = (struct iso_directory_record *) (buf->data + (int) filp->pos % CDFS_BLOCKSIZE);
reclen = isonum_711(rec->length);
namelen = isonum_711(rec->name_len);
// Check for no more records in block
if (reclen == 0)
{
int blkleft = CDFS_BLOCKSIZE - ((int) filp->pos % CDFS_BLOCKSIZE);
release_buffer(cdfs->cache, buf);
filp->pos += blkleft;
goto blkagain;
}
// Check for . and .. entries
if (namelen == 1 && (rec->name[0] == 0 || rec->name[0] == 1))
{
filp->pos += reclen;
goto recagain;
}
// Get info from directory record
dirp->ino = isonum_733(rec->extent);
dirp->reclen = sizeof(struct direntry) - MAXPATH + namelen + 1;
if (cdfs->joliet)
{
int n;
namelen /= 2;
wname = (wchar_t *) rec->name;
if (namelen > 1 && ntohs(wname[namelen - 2]) == ';') namelen -= 2;
if (namelen > 0 && ntohs(wname[namelen - 1]) == '.') namelen -= 1;
dirp->namelen = namelen;
for (n = 0; n < namelen; n++) dirp->name[n] = (char) ntohs(wname[n]);
dirp->name[namelen] = 0;
}
else
{
name = (char *) rec->name;
if (namelen > 1 && name[namelen - 2] == ';') namelen -= 2;
if (namelen > 0 && name[namelen - 1] == '.') namelen -= 1;
dirp->namelen = namelen;
memcpy(dirp->name, name, namelen);
dirp->name[namelen] = 0;
}
filp->pos += reclen;
release_buffer(cdfs->cache, buf);
return 1;
}
struct fsops cdfsops =
{
FSOP_OPEN | FSOP_CLOSE | FSOP_FSYNC | FSOP_READ |
FSOP_TELL | FSOP_LSEEK | FSOP_STAT | FSOP_FSTAT |
FSOP_OPENDIR | FSOP_READDIR,
NULL,
NULL,
NULL,
cdfs_mount,
cdfs_umount,
cdfs_statfs,
cdfs_open,
cdfs_close,
NULL,
cdfs_fsync,
cdfs_read,
NULL,
NULL,
cdfs_tell,
cdfs_lseek,
NULL,
NULL,
NULL,
cdfs_fstat,
cdfs_stat,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
cdfs_opendir,
cdfs_readdir
};
void init_cdfs()
{
register_filesystem("cdfs", &cdfsops);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -