⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdfs.c

📁 一个小型操作系统的源代码,其目的仅 仅是为了在x86电脑上在没有windows 操作系统的情况下能使用java虚拟机。 研究操作系统的好东西。
💻 C
📖 第 1 页 / 共 2 页
字号:
  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 + -