📄 fatfs.c
字号:
/* */COUNT dos_getftime(COUNT fd, date FAR * dp, time FAR * tp){ f_node_ptr fnp; /* Translate the fd into an fnode pointer, since all internal */ /* operations are achieved through fnodes. */ 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_INVLDHNDL; /* Get the date and time from the fnode and return */ *dp = fnp->f_dir.dir_date; *tp = fnp->f_dir.dir_time; release_near_f_node(fnp); return SUCCESS;}/* *//* dos_setftime for the file time *//* */COUNT dos_setftime(COUNT fd, date dp, time tp){ f_node_ptr fnp; /* Translate the fd into an fnode pointer, since all internal */ /* operations are achieved through fnodes. */ 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_INVLDHNDL; /* Set the date and time from the fnode and return */ fnp->f_dir.dir_date = dp; fnp->f_dir.dir_time = tp; /* mark file as modified and set this date upon closing */ fnp->f_flags |= F_DMOD | F_DDATE; save_far_f_node(fnp); return SUCCESS;}/* *//* dos_getfsize for the file time *//* */ULONG dos_getfsize(COUNT fd){ f_node_ptr fnp; /* Translate the fd into an fnode pointer, since all internal */ /* operations are achieved through fnodes. */ 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 (ULONG)-1l; /* Return the file size */ release_near_f_node(fnp); return fnp->f_dir.dir_size;}/* *//* dos_setfsize for the file time *//* */BOOL dos_setfsize(COUNT fd, LONG size){ f_node_ptr fnp; /* Translate the fd into an fnode pointer, since all internal */ /* operations are achieved through fnodes. */ 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 FALSE; /* Change the file size */ fnp->f_dir.dir_size = size; merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ save_far_f_node(fnp); return TRUE;}/* *//* Find free cluster in disk FAT table *//* */STATIC CLUSTER find_fat_free(f_node_ptr fnp){ REG CLUSTER idx, size; struct dpb FAR *dpbp = fnp->f_dpb;#ifdef DISPLAY_GETBLOCK printf("[find_fat_free]\n");#endif /* Start from optimized lookup point for start of FAT */ idx = 2; size = dpbp->dpb_size;#ifdef WITHFAT32 if (ISFAT32(dpbp)) { if (dpbp->dpb_xcluster != UNKNCLUSTER) idx = dpbp->dpb_xcluster; size = dpbp->dpb_xsize; } else#endif if (dpbp->dpb_cluster != UNKNCLUSTER) idx = dpbp->dpb_cluster; /* Search the FAT table looking for the first free */ /* entry. */ for (; idx <= size; idx++) { if (next_cluster(dpbp, idx) == FREE) break; }#ifdef WITHFAT32 if (ISFAT32(dpbp)) { dpbp->dpb_xcluster = idx; if (idx > size) { /* No empty clusters, disk is FULL! */ dpbp->dpb_xcluster = UNKNCLUSTER; idx = LONG_LAST_CLUSTER; } /* return the free entry */ write_fsinfo(dpbp); return idx; }#endif dpbp->dpb_cluster = (UWORD)idx; if ((UWORD)idx > (UWORD)size) { /* No empty clusters, disk is FULL! */ dpbp->dpb_cluster = UNKNCLUSTER; idx = LONG_LAST_CLUSTER; } /* return the free entry */ return idx;}/* *//* create a directory - returns success or a negative error *//* number *//* */COUNT dos_mkdir(BYTE * dir){ REG f_node_ptr fnp; REG COUNT idx; struct buffer FAR *bp; struct dpb FAR *dpbp; CLUSTER free_fat, parent; COUNT ret; char fcbname[FNAME_SIZE + FEXT_SIZE]; /* first split the passed dir into components (i.e. - */ /* path to new directory and name of new directory */ if ((fnp = split_path(dir, fcbname)) == NULL) { return DE_PATHNOTFND; } /* check that the resulting combined path does not exceed the 67 MAX_CDSPATH limit. this leads to problems: A) you can't CD to this directory later B) you can't create files in this subdirectory C) the created dir will not be found later, so you can create an unlimited amount of same dirs. this space is lost forever */ if (strlen(dir) >= MAX_CDSPATH) /* dir is already output of "truename" */ { dir_close(fnp); return DE_PATHNOTFND; } /* Check that we don't have a duplicate name, so if we */ /* find one, it's an error. */ if (find_fname(fnp, fcbname, D_ALL)) { dir_close(fnp); return DE_ACCESS; } parent = fnp->f_dirstart; ret = alloc_find_free(fnp, dir, fcbname); if (ret != SUCCESS) return ret; /* get an empty cluster, so that we make it into a */ /* directory. */ /* TE this has to be done (and failed) BEFORE the dir entry */ /* is changed */ free_fat = find_fat_free(fnp); /* No empty clusters, disk is FULL! Translate into a */ /* useful error message. */ if (free_fat == LONG_LAST_CLUSTER) { dir_close(fnp); return DE_HNDLDSKFULL; } /* Set the fnode to the desired mode */ fnp->f_mode = WRONLY; init_direntry(&fnp->f_dir, D_DIR, free_fat, fcbname); fnp->f_flags = F_DMOD | F_DDIR; fnp->f_offset = 0l; /* Mark the cluster in the FAT as used */ dpbp = fnp->f_dpb; link_fat(dpbp, free_fat, LONG_LAST_CLUSTER); /* Craft the new directory. Note that if we're in a new */ /* directory just under the root, ".." pointer is 0. */ /* as we are overwriting it completely, don't read first */ bp = getblockOver(clus2phys(free_fat, dpbp), dpbp->dpb_unit);#ifdef DISPLAY_GETBLOCK printf("FAT (dos_mkdir)\n");#endif if (bp == NULL) { dir_close(fnp); return DE_BLKINVLD; } /* Create the "." entry */ init_direntry(&DirEntBuffer, D_DIR, free_fat, ". "); /* And put it out */ putdirent(&DirEntBuffer, bp->b_buffer); /* create the ".." entry */ DirEntBuffer.dir_name[1] = '.';#ifdef WITHFAT32 if (ISFAT32(dpbp) && parent == dpbp->dpb_xrootclst) { parent = 0; }#endif setdstart(dpbp, &DirEntBuffer, parent); /* and put it out */ putdirent(&DirEntBuffer, &bp->b_buffer[DIRENT_SIZE]); /* fill the rest of the block with zeros */ fmemset(&bp->b_buffer[2 * DIRENT_SIZE], 0, BUFFERSIZE - 2 * DIRENT_SIZE); /* Mark the block to be written out */ bp->b_flag |= BFR_DIRTY | BFR_VALID; /* clear out the rest of the blocks in the cluster */ for (idx = 1; idx <= dpbp->dpb_clsmask; idx++) { /* as we are overwriting it completely, don't read first */ bp = getblockOver(clus2phys(getdstart(dpbp, &fnp->f_dir), dpbp) + idx, dpbp->dpb_unit);#ifdef DISPLAY_GETBLOCK printf("DIR (dos_mkdir)\n");#endif if (bp == NULL) { dir_close(fnp); return DE_BLKINVLD; } fmemset(bp->b_buffer, 0, BUFFERSIZE); bp->b_flag |= BFR_DIRTY | BFR_VALID | BFR_UNCACHE; /* need not be cached */ } /* flush the drive buffers so that all info is written */ /* hazard: no error checking! */ flush_buffers(dpbp->dpb_unit); /* Close the directory so that the entry is updated */ fnp->f_flags |= F_DMOD; dir_close(fnp); return SUCCESS;}STATIC CLUSTER extend(f_node_ptr fnp){ CLUSTER free_fat; /* get an empty cluster, so that we use it to extend the file. */ free_fat = find_fat_free(fnp); /* No empty clusters, disk is FULL! Translate into a useful */ /* error message. */ if (free_fat == LONG_LAST_CLUSTER) return free_fat; /* Now that we've found a free FAT entry, mark it as the last */ /* entry and save. */ if (fnp->f_cluster == FREE) setdstart(fnp->f_dpb, &fnp->f_dir, free_fat); else link_fat(fnp->f_dpb, fnp->f_cluster, free_fat); link_fat(fnp->f_dpb, free_fat, LONG_LAST_CLUSTER); /* Mark the directory so that the entry is updated */ fnp->f_flags |= F_DMOD; return free_fat;}STATIC COUNT extend_dir(f_node_ptr fnp){ REG COUNT idx; CLUSTER cluster = extend(fnp); if (cluster == LONG_LAST_CLUSTER) { dir_close(fnp); return DE_HNDLDSKFULL; } /* clear out the blocks in the cluster */ for (idx = 0; idx <= fnp->f_dpb->dpb_clsmask; idx++) { REG struct buffer FAR *bp; /* as we are overwriting it completely, don't read first */ bp = getblockOver(clus2phys(cluster, fnp->f_dpb) + idx, fnp->f_dpb->dpb_unit);#ifdef DISPLAY_GETBLOCK printf("DIR (extend_dir)\n");#endif if (bp == NULL) { dir_close(fnp); return DE_BLKINVLD; } fmemset(bp->b_buffer, 0, BUFFERSIZE); bp->b_flag |= BFR_DIRTY | BFR_VALID; if (idx != 0) bp->b_flag |= BFR_UNCACHE; /* needs not be cached */ } if (!find_free(fnp)) { dir_close(fnp); return DE_HNDLDSKFULL; } /* flush the drive buffers so that all info is written */ /* hazard: no error checking! */ flush_buffers(fnp->f_dpb->dpb_unit); return SUCCESS;}/* Description. * Finds the cluster which contains byte at the fnp->f_offset offset and * stores its number to the fnp->f_cluster. The search begins from the start of * a file or a directory depending whether fnp->f_ddir is FALSE or TRUE * and continues through the FAT chain until the target cluster is found. * The mode can have only XFR_READ or XFR_WRITE values. * In the XFR_WRITE mode map_cluster extends the FAT chain by creating * new clusters upon necessity. * Return value. * DE_HNDLDSKFULL - [XFR_WRITE mode only] unable to find free cluster * for extending the FAT chain, the disk is full. * The fnode is released from memory. * DE_SEEK - [XFR_READ mode only] byte at f_offset lies outside of * the FAT chain. The fnode is not released. * Notes. * If we are moving forward, then use the relative cluster number offset * that we are at now (f_cluster_offset) to start, instead of starting * at the beginning. */COUNT map_cluster(REG f_node_ptr fnp, COUNT mode){ CLUSTER relcluster, cluster;#ifdef DISPLAY_GETBLOCK printf("map_cluster: current %lu, offset %lu, diff=%lu ", (ULONG)fnp->f_cluster_offset, fnp->f_offset, fnp->f_offset - fnp->f_cluster_offset);#endif if (fnp->f_cluster == FREE) { /* If this is a read but the file still has zero bytes return */ /* immediately.... */ if (mode == XFR_READ) return DE_SEEK; /* If someone did a seek, but no writes have occured, we will */ /* need to initialize the fnode. */ /* (mode == XFR_WRITE) */ /* If there are no more free fat entries, then we are full! */ cluster = extend(fnp); if (cluster == LONG_LAST_CLUSTER) { return DE_HNDLDSKFULL; } fnp->f_cluster = cluster; } relcluster = (CLUSTER)((fnp->f_offset / fnp->f_dpb->dpb_secsize) >> fnp->f_dpb->dpb_shftcnt); if (relcluster < fnp->f_cluster_offset) { /* Set internal index and cluster size. */ fnp->f_cluster = (fnp->f_flags & F_DDIR) ? fnp->f_dirstart : getdstart(fnp->f_dpb, &fnp->f_dir); fnp->f_cluster_offset = 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -