Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<errno.h>
  5. #include<fcntl.h>
  6. #include<menuet/os.h>
  7.  
  8. struct systree_blk
  9. {
  10.  unsigned long cmd,pos,blks;
  11.  void * data,* work;
  12.  char name[256];
  13. } __attribute__((packed));
  14.  
  15. typedef struct EMU_FILE
  16. {
  17.  int                    handle;
  18.  unsigned long          size;
  19.  unsigned long          pos;
  20.  unsigned long          mode;
  21.  unsigned long          current_sector;
  22.  unsigned long          size_sectors;
  23.  char                 * write_buf;
  24.  unsigned long          write_bufsize;
  25.  char                   rd_buffer[512];
  26.  char                   name[256];
  27.  unsigned char          dirty;
  28. } EMU_FILE;
  29.  
  30. #define _MAX_HANDLES            64
  31.  
  32. static EMU_FILE         * EMU_file_table[_MAX_HANDLES];
  33. static char               systree_work_area[16384+512];
  34. static volatile struct systree_blk sblk;
  35. static volatile int S_eax,S_ebx;
  36.  
  37. static inline int EMU_alloc_handle(void)
  38. {
  39.  register int i;
  40.  for(i=0;i<_MAX_HANDLES;i++)
  41.   if(!EMU_file_table[i])
  42.   {
  43.    EMU_file_table[i]=(EMU_FILE *)malloc(sizeof(EMU_FILE));
  44.    if(!EMU_file_table[i]) return -ENOMEM;
  45.    return i;
  46.   }
  47.  return -EAGAIN;
  48. }
  49.  
  50. static inline int EMU_systree_cmd(void)
  51. {
  52.  __asm__ __volatile__("int $0x40"
  53.      :"=a"(S_eax),"=b"(S_ebx)
  54.      :"0"(58),"1"((void *)&sblk));
  55.  return S_eax;
  56. }
  57.  
  58. static int EMU_loadsector(EMU_FILE * filp)
  59. {
  60.  sblk.cmd=0;
  61.  sblk.pos=filp->current_sector;
  62.  sblk.blks=1;
  63.  sblk.data=filp->rd_buffer;
  64.  sblk.work=systree_work_area;
  65.  memcpy((void *)&sblk.name,(const void *)filp->name,strlen(filp->name)+1);
  66.  return EMU_systree_cmd();
  67. }
  68.  
  69. static int EMU_fsync(EMU_FILE * filp)
  70. {
  71.  if(filp->mode==O_RDONLY) return 0;
  72.  if(!filp->dirty) return 0;
  73.  filp->dirty=0;
  74.  sblk.cmd=1;
  75.  sblk.pos=0;
  76.  sblk.blks=filp->size;
  77.  sblk.data=filp->write_buf;
  78.  sblk.work=systree_work_area;
  79.  memcpy((void *)sblk.name,(const void *)filp->name,strlen(filp->name)+1);
  80.  return EMU_systree_cmd();
  81. }
  82.  
  83. static inline int EMU_realloc_buf(EMU_FILE * filp,unsigned long newsize)
  84. {
  85.  char * n;
  86.  newsize=(newsize+511)&~511;
  87.  if(filp->write_bufsize==newsize) return 0;
  88.  n=(char *)realloc(filp->write_buf,newsize);
  89.  if(!n) return -ENOSPC;
  90.  filp->write_buf=n;
  91.  filp->write_bufsize=newsize;
  92.  filp->dirty=1;
  93.  return 0;
  94. }
  95.  
  96. static int EMU_createtrunc(char * fname)
  97. {
  98.  sblk.cmd=1;
  99.  sblk.pos=0;
  100.  sblk.blks=0;
  101.  sblk.data=sblk.work=systree_work_area;
  102.  memcpy((void *)sblk.name,(const void *)fname,strlen(fname)+1);
  103.  return EMU_systree_cmd();
  104. }
  105.  
  106. static int EMU_getfsize(char * fname,unsigned long * sizep)
  107. {
  108.  sblk.cmd=0;
  109.  sblk.pos=0;
  110.  sblk.blks=1;
  111.  sblk.data=systree_work_area+16384;
  112.  sblk.work=systree_work_area;
  113.  memcpy((void *)sblk.name,(const void *)fname,strlen(fname)+1);
  114.  if(EMU_systree_cmd()!=0) return -EINVAL;
  115.  if(sizep) *sizep=(unsigned long)S_ebx;
  116.  return 0;
  117. }
  118.  
  119. static int EMU_open(char * fname,int mode)
  120. {
  121.  EMU_FILE * filp;
  122.  register int hid;
  123.  unsigned long iomode;
  124.  hid=EMU_alloc_handle();
  125.  if(hid<0) return hid;
  126.  filp=EMU_file_table[hid];
  127.  filp->handle=hid;
  128.  iomode=mode&(O_RDONLY|O_WRONLY|O_RDWR);
  129.  memcpy((void *)filp->name,(const void *)fname,strlen(fname)+1);
  130.  strupr(filp->name);
  131.  filp->mode=iomode;
  132.  if(mode&O_CREAT)
  133.  {
  134.   int createflags=mode&(O_TRUNC|O_EXCL);
  135.   if(createflags&O_EXCL)
  136.   {
  137.    unsigned long psz=0;
  138.    if(EMU_getfsize(filp->name,&psz)==0)
  139.    {
  140.     free(EMU_file_table[hid=filp->handle]);
  141.     EMU_file_table[hid]=NULL;
  142.     return -EEXIST;
  143.    }
  144.   }
  145.   if(createflags&O_TRUNC)
  146.   {
  147.    EMU_createtrunc(filp->name);
  148.   }
  149.  }
  150.  if(iomode==O_RDONLY)
  151.  {
  152.   hid=EMU_getfsize(filp->name,&filp->size);
  153.   if(hid<0)
  154.   {
  155.    free(EMU_file_table[hid=filp->handle]);
  156.    EMU_file_table[hid]=NULL;
  157.    return -ENOENT;
  158.   }
  159.   filp->current_sector=0;
  160.   if(EMU_loadsector(filp)<0) filp->current_sector=-1UL;
  161.   filp->mode=O_RDONLY;
  162.   filp->size_sectors=(filp->size+511)/512;
  163.   filp->write_bufsize=0;
  164.   filp->dirty=0;
  165.   return filp->handle;
  166.  }
  167.  if(iomode==O_WRONLY)
  168.  {
  169.   hid=EMU_getfsize(filp->name,&filp->size);
  170.   if(hid<0)
  171.   {
  172. BAD_WRO:
  173.    free(EMU_file_table[hid=filp->handle]);
  174.    EMU_file_table[hid]=NULL;
  175.    return -ENOENT;
  176.   }
  177.   filp->current_sector=-1UL;
  178.   filp->mode=O_WRONLY;
  179.   filp->size_sectors=0;
  180.   filp->write_bufsize=(filp->size+511)&~511;
  181.   filp->write_buf=(char *)malloc(filp->write_bufsize);
  182.   if(!filp->write_buf)
  183.   {
  184.    free(filp->write_buf);
  185.    goto BAD_WRO;
  186.   }
  187.   sblk.cmd=0;
  188.   sblk.pos=0;
  189.   sblk.blks=filp->write_bufsize/512;
  190.   sblk.data=filp->write_buf;
  191.   sblk.work=systree_work_area;
  192.   if(EMU_systree_cmd()!=0) goto BAD_WRO1;
  193.   return filp->handle;
  194.  }
  195.  hid=EMU_getfsize(filp->name,&filp->size);
  196.  if(hid<0)
  197.  {
  198. BAD_WRO1:
  199.   free(EMU_file_table[hid=filp->handle]);
  200.   EMU_file_table[hid]=NULL;
  201.   return -ENOENT;
  202.  }
  203.  filp->current_sector=-1UL;
  204.  filp->mode=O_RDWR;
  205.  filp->size_sectors=0;
  206.  filp->write_bufsize=(filp->size+511)&~511;
  207.  filp->write_buf=(char *)malloc(filp->write_bufsize);
  208.  if(!filp->write_buf)
  209.  {
  210.   free(filp->write_buf);
  211.   goto BAD_WRO1;
  212.  }
  213.  sblk.cmd=0;
  214.  sblk.pos=0;
  215.  sblk.blks=filp->write_bufsize/512;
  216.  sblk.data=filp->write_buf;
  217.  sblk.work=systree_work_area;
  218.  if(EMU_systree_cmd()!=0) goto BAD_WRO1;
  219.  return filp->handle;
  220. }
  221.  
  222. static int EMU_close(EMU_FILE * filp)
  223. {
  224.  int hid;
  225.  if(!filp) return -ENOENT;
  226.  if(EMU_file_table[hid=filp->handle]!=filp) return -EBADF;
  227.  if(filp->write_buf) free(filp->write_buf);
  228.  free(filp);
  229.  EMU_file_table[hid]=NULL;
  230.  return 0;
  231. }
  232.  
  233. static int EMU_lseek(EMU_FILE * filp,unsigned long off,int whence)
  234. {
  235.  unsigned long newpos;
  236.  switch(whence)
  237.  {
  238.   case SEEK_SET:
  239.    newpos=off;
  240.    break;
  241.   case SEEK_CUR:
  242.    newpos=filp->pos+off;
  243.    break;
  244.   case SEEK_END:
  245.    newpos=filp->size+off-1;
  246.    break;
  247.  }
  248.  if(newpos>=filp->size) return -1;
  249.  filp->pos=newpos;
  250.  return filp->pos;
  251. }
  252.  
  253. static int EMU_read(EMU_FILE * filp,unsigned long size,void * buf)
  254. {
  255.  int icount,curr_sector,curr_sector_ofs,n;
  256.  int nbufbytes,totalremaining;
  257.  if(filp->pos+count>filp->size)
  258.   count=filp->size-filp->pos;
  259.  if(filp->mode==O_RDWR)
  260.  {
  261.   memcpy(buffer,filp->write_buf+filp->pos,count);
  262.   filp->pos+=count;
  263.   return count;
  264.  }
  265.  icount=count;
  266.  while(count>0)
  267.  {
  268.   if(filp->pos>=filp->size) return icount=count;
  269.   curr_sector=sh->pointer>>9;
  270.   curr_sector_ofs=sh->pointer&511;
  271.   n=count;
  272.   if(sh->bufsector==-1 || curr_sector!=sh->bufsector)
  273.   {
  274.    if(dosemu_loadcurrsector(sh)==-1) return -1;
  275.   }
  276.   nbufbytes=512-curr_sector_ofs;
  277.   totalremaining=sh->size-sh->pointer;
  278.   if(nbufbytes>totalremaining) nbufbytes=totalremaining;
  279.   if(n>nbufbytes) n=nbufbytes;
  280.   memcpy(buffer,&sh->buf[curr_sector_ofs],n);
  281.   buffer+=n;
  282.   count-=n;
  283.   sh->pointer+=n;
  284.  }
  285.  return icount;
  286. }
  287. }
  288.