📄 fatfs.c
字号:
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 + -