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

📄 fatfs.c

📁 GNU FreeDOS兼容MS DOS很好的东东.
💻 C
📖 第 1 页 / 共 5 页
字号:
  update_pointers:    ret_cnt += xfr_cnt;    to_xfer -= xfr_cnt;    buffer = adjust_far((char FAR *)buffer + xfr_cnt);    if (mode == XFR_WRITE)    {      if (fnp->f_offset > fnp->f_dir.dir_size)      {        fnp->f_dir.dir_size = fnp->f_offset;      }      merge_file_changes(fnp, FALSE);     /* /// Added - Ron Cemer */    }  }  save_far_f_node(fnp);  return ret_cnt;}/* Position the file pointer to the desired offset                      *//* Returns a long current offset or a negative error code               */LONG dos_lseek(COUNT fd, LONG foffset, COUNT origin){  REG f_node_ptr fnp;  /* Translate the fd into a useful pointer                       */  fnp = xlt_fd(fd);  /* If the fd was invalid because it was out of range or the     */  /* requested file was not open, tell the caller and exit                */  /* note: an invalid fd is indicated by a 0 return               */  if (fnp == (f_node_ptr) 0)    return (LONG) DE_INVLDHNDL;  /* now do the actual lseek adjustment to the file poitner       */  switch (origin)  {      /* offset from beginning of file                                */    case 0:      fnp->f_offset = (ULONG) foffset;      break;      /* offset from current location                                 */    case 1:      fnp->f_offset += foffset;      break;      /* offset from eof                                              */    case 2:      fnp->f_offset = fnp->f_dir.dir_size + foffset;      break;      /* default to an invalid function                               */    default:      release_near_f_node(fnp);      return (LONG) DE_INVLDFUNC;  }  save_far_f_node(fnp);  return fnp->f_offset;}/* returns the number of unused clusters */CLUSTER dos_free(struct dpb FAR * dpbp){  /* There's an unwritten rule here. All fs       */  /* cluster start at 2 and run to max_cluster+2  */  REG CLUSTER i;  REG CLUSTER cnt = 0;  CLUSTER max_cluster = dpbp->dpb_size;#ifdef WITHFAT32  if (ISFAT32(dpbp))  {    if (dpbp->dpb_xnfreeclst != XUNKNCLSTFREE)      return dpbp->dpb_xnfreeclst;    max_cluster = dpbp->dpb_xsize;  }  else#endif  if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)    return dpbp->dpb_nfreeclst;  for (i = 2; i <= max_cluster; i++)  {    if (next_cluster(dpbp, i) == 0)      ++cnt;  }#ifdef WITHFAT32  if (ISFAT32(dpbp))  {    dpbp->dpb_xnfreeclst = cnt;    write_fsinfo(dpbp);    return cnt;  }#endif  dpbp->dpb_nfreeclst = (UWORD)cnt;  return cnt;}#ifndef IPLint dos_cd(char * PathName){  f_node_ptr fnp;  struct cds FAR *cdsp = get_cds(PathName[0] - 'A');  if ((media_check(cdsp->cdsDpb) < 0))    return DE_INVLDDRV;  /* now test for its existance. If it doesn't, return an error.  */  if ((fnp = dir_open(PathName)) == NULL)    return DE_PATHNOTFND;  /* problem: RBIL table 01643 does not give a FAT32 field for the     CDS start cluster. But we are not using this field ourselves */  cdsp->cdsStrtClst = (UWORD)fnp->f_dirstart;  dir_close(fnp);  return SUCCESS;}#endif/* try to allocate a near f_node                            *//* (there are just two of them, in the SDA)                 */f_node_ptr get_near_f_node(void){  f_node_ptr fnp = fnode;  if (fnp->f_count == 0)    fnp->f_count++;  else  {    fnp++;    if (fnp->f_count == 0)      fnp->f_count++;    else    {      fnp = (f_node_ptr) 0;      panic("more than two near fnodes requested at the same time!\n");    }  }  return fnp;}/* Try to allocate an f_node from the available files array */f_node_ptr get_f_node(void){  REG int i;  f_node_ptr fnp = get_near_f_node();  if (fnp != (f_node_ptr)0)  {    for (i = 0; i < f_nodes_cnt; i++)    {      if (f_nodes[i].f_count == 0)      {        ++f_nodes[i].f_count;        fnode_fd[fnp - fnode] = i;        return fnp;      }    }    release_near_f_node(fnp);  }  return (f_node_ptr) 0;}VOID release_f_node(f_node_ptr fnp){  struct f_node FAR *fp = &f_nodes[xlt_fnp(fnp)];  if (fp->f_count > 0)    --fp->f_count;  else    fp->f_count = 0;  release_near_f_node(fnp);}#ifndef IPLCOUNT dos_getfattr_fd(COUNT fd){  f_node_ptr fnp = xlt_fd(fd);  /* If the fd was invalid because it was out of range or the     */  /* requested file was not open, tell the caller and exit        */  /* note: an invalid fd is indicated by a 0 return               */  if (fnp == (f_node_ptr) 0)    return DE_TOOMANY;  release_near_f_node(fnp);  return fnp->f_dir.dir_attrib;}COUNT dos_getfattr(BYTE * name){  COUNT result, fd;  fd = (short)dos_open(name, O_RDONLY | O_OPEN, 0);  if (fd < SUCCESS)    return fd;  result = dos_getfattr_fd(fd);  dos_close(fd);  return result;}COUNT dos_setfattr(BYTE * name, UWORD attrp){  COUNT fd;  f_node_ptr fnp;  /* JPP-If user tries to set VOLID or RESERVED bits, return error.     We used to also check for D_DIR here, but causes issues with deltree     which is trying to work around another issue.  So now we check     these here, and only report DE_ACCESS if user tries to set directory     bit on a non-directory entry.   */  if ((attrp & (D_VOLID | 0xC0)) != 0)    return DE_ACCESS;  fd = (short)dos_open(name, O_RDONLY | O_OPEN, 0);  if (fd < SUCCESS)    return fd;  fnp = xlt_fd(fd);    /* Set the attribute from the fnode and return          */  /* clear all attributes but DIR and VOLID */  fnp->f_dir.dir_attrib &= (D_VOLID | D_DIR);   /* JPP */  /* if caller tries to set DIR on non-directory, return error */  if ((attrp & D_DIR) && !(fnp->f_dir.dir_attrib & D_DIR))  {    dos_close(fd);    return DE_ACCESS;  }      /* set attributes that user requested */  fnp->f_dir.dir_attrib |= attrp;       /* JPP */  fnp->f_flags |= F_DMOD | F_DDATE;  merge_file_changes(fnp, FALSE);  save_far_f_node(fnp);  dos_close(fd);  return SUCCESS;}#endif#ifdef WITHFAT32VOID dpb16to32(struct dpb FAR *dpbp){  dpbp->dpb_xflags = 0;  dpbp->dpb_xfsinfosec = 0xffff;  dpbp->dpb_xbackupsec = 0xffff;  dpbp->dpb_xrootclst = 0;  dpbp->dpb_xdata = dpbp->dpb_data;  dpbp->dpb_xsize = dpbp->dpb_size;}VOID bpb_to_dpb(bpb FAR * bpbp, REG struct dpb FAR * dpbp, BOOL extended)#elseVOID bpb_to_dpb(bpb FAR * bpbp, REG struct dpb FAR * dpbp)#endif{  ULONG size;  REG UWORD shftcnt;  bpb sbpb;  fmemcpy(&sbpb, bpbp, sizeof(sbpb));  for (shftcnt = 0; (sbpb.bpb_nsector >> shftcnt) > 1; shftcnt++)    ;  dpbp->dpb_shftcnt = shftcnt;  dpbp->dpb_mdb = sbpb.bpb_mdesc;  dpbp->dpb_secsize = sbpb.bpb_nbyte;  dpbp->dpb_clsmask = sbpb.bpb_nsector - 1;  dpbp->dpb_fatstrt = sbpb.bpb_nreserved;  dpbp->dpb_fats = sbpb.bpb_nfat;  dpbp->dpb_dirents = sbpb.bpb_ndirent;  size = sbpb.bpb_nsize == 0 ? sbpb.bpb_huge : (ULONG) sbpb.bpb_nsize;  dpbp->dpb_fatsize = sbpb.bpb_nfsect;  dpbp->dpb_dirstrt = dpbp->dpb_fatstrt + dpbp->dpb_fats * dpbp->dpb_fatsize;  dpbp->dpb_data = dpbp->dpb_dirstrt      + (dpbp->dpb_dirents + dpbp->dpb_secsize/DIRENT_SIZE - 1) /          (dpbp->dpb_secsize/DIRENT_SIZE);  dpbp->dpb_size = (UWORD)((size - dpbp->dpb_data) >> shftcnt) + 1;  { /* Make sure the number of FAT sectors is actually enough to hold that */    /* many clusters. Otherwise back the number of clusters down (LG & AB) */    unsigned fatsiz;    ULONG tmp = dpbp->dpb_fatsize * (ULONG)(dpbp->dpb_secsize / 2);/* entries/2 */    if (tmp >= 0x10000UL)      goto ckok;    fatsiz = (unsigned) tmp;    if (dpbp->dpb_size > FAT_MAGIC) {/* FAT16 */      if (fatsiz <= FAT_MAGIC)       /* FAT12 - let it pass through rather */        goto ckok;                   /* than lose data correcting FAT type */    } else {                         /* FAT12 */      if (fatsiz >= 0x4000)        goto ckok;      fatsiz = fatsiz * 4 / 3;    }    if (dpbp->dpb_size >= fatsiz)    /* FAT too short */      dpbp->dpb_size = fatsiz - 1;   /* - 2 reserved entries + 1 */ckok:;  }  dpbp->dpb_flags = 0;  dpbp->dpb_cluster = UNKNCLUSTER;  /* number of free clusters */  dpbp->dpb_nfreeclst = UNKNCLSTFREE;#ifdef WITHFAT32  if (extended)  {    dpbp->dpb_xfatsize = sbpb.bpb_nfsect == 0 ? sbpb.bpb_xnfsect        : sbpb.bpb_nfsect;    dpbp->dpb_xcluster = UNKNCLUSTER;    dpbp->dpb_xnfreeclst = XUNKNCLSTFREE;       /* number of free clusters */    dpb16to32(dpbp);    if (ISFAT32(dpbp))    {      dpbp->dpb_xflags = sbpb.bpb_xflags;      dpbp->dpb_xfsinfosec = sbpb.bpb_xfsinfosec;      dpbp->dpb_xbackupsec = sbpb.bpb_xbackupsec;      dpbp->dpb_dirents = 0;      dpbp->dpb_dirstrt = 0xffff;      dpbp->dpb_size = 0;      dpbp->dpb_xdata =          dpbp->dpb_fatstrt + dpbp->dpb_fats * dpbp->dpb_xfatsize;      dpbp->dpb_xsize = ((size - dpbp->dpb_xdata) >> shftcnt) + 1;      dpbp->dpb_xrootclst = sbpb.bpb_xrootclst;      read_fsinfo(dpbp);    }  }#endif}STATIC int rqblockio(unsigned char command, struct dpb FAR * dpbp){ retry:  MediaReqHdr.r_length = sizeof(request);  MediaReqHdr.r_unit = dpbp->dpb_subunit;  MediaReqHdr.r_command = command;  MediaReqHdr.r_mcmdesc = dpbp->dpb_mdb;  MediaReqHdr.r_status = 0;  if (command == C_BLDBPB) /* help USBASPI.SYS & DI1000DD.SYS (TE) */    MediaReqHdr.r_bpfat = (boot FAR *)DiskTransferBuffer;  execrh((request FAR *) & MediaReqHdr, dpbp->dpb_device);  if ((MediaReqHdr.r_status & S_ERROR) || !(MediaReqHdr.r_status & S_DONE))  {    FOREVER    {      switch (block_error(&MediaReqHdr, dpbp->dpb_unit, dpbp->dpb_device, 0))      {      case ABORT:      case FAIL:        return DE_INVLDDRV;      case RETRY:        goto retry;      case CONTINUE:        return SUCCESS;      }    }  }  return SUCCESS;}COUNT media_check(REG struct dpb FAR * dpbp){  int ret;  if (dpbp == NULL)    return DE_INVLDDRV;  /* First test if anyone has changed the removable media         */  ret = rqblockio(C_MEDIACHK, dpbp);  if (ret < SUCCESS)    return ret;  switch (MediaReqHdr.r_mcretcode | dpbp->dpb_flags)  {    case M_NOT_CHANGED:      /* It was definitely not changed, so ignore it          */      return SUCCESS;      /* If it is forced or the media may have changed,       */      /* rebuild the bpb                                      */    case M_DONT_KNOW:        /* hazard: no error checking! */      flush_buffers(dpbp->dpb_unit);      /* If it definitely changed, don't know (falls through) */      /* or has been changed, rebuild the bpb.                */    /* case M_CHANGED: */    default:      setinvld(dpbp->dpb_unit);      ret = rqblockio(C_BLDBPB, dpbp);      if (ret < SUCCESS)        return ret;#ifdef WITHFAT32      /* extend dpb only for internal or FAT32 devices */      bpb_to_dpb(MediaReqHdr.r_bpptr, dpbp,                 ISFAT32(dpbp) || FP_SEG(dpbp) == FP_SEG(&os_major));#else      bpb_to_dpb(MediaReqHdr.r_bpptr, dpbp);#endif      return SUCCESS;  }}/* translate the f_node pointer into an fd                  */COUNT xlt_fnp(f_node_ptr fnp){  return fnode_fd[fnp - fnode];}/* allocate a near fnode and copy the far fd fnode to it */f_node_ptr xlt_fd(int fd){  f_node_ptr fnp = (f_node_ptr) 0;  /* If the fd was invalid because it was out of range or the     */  /* requested file was not open, tell the caller and exit        */  /* note: an invalid fd is indicated by a 0 return               */  if (fd < f_nodes_cnt)  {    fnp = get_near_f_node();    if (fnp != (f_node_ptr)0)    {      fmemcpy(fnp, &f_nodes[fd], sizeof(*fnp));      if (fnp->f_count <= 0)      {        rele

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -