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

📄 fatfs.c

📁 GNU FreeDOS兼容MS DOS很好的东东.
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* If more than one f_node has a file open, and a write       occurs, this function must be called to propagate the       results of that write to the other f_nodes which have       that file open.  Note that this function only has an       effect if SHARE is installed.  This is for compatibility       reasons, since DOS without SHARE does not share changes       between two or more open instances of the same file       unless these instances were generated by dup() or dup2(). */STATIC void merge_file_changes(f_node_ptr fnp, int collect){  f_node_ptr fnp2;  int i, fd;  if (!IsShareInstalled())    return;  fd = xlt_fnp(fnp);  fnp2 = get_near_f_node();  for (i = 0; i < f_nodes_cnt; i++)  {    fmemcpy(fnp2, &f_nodes[i], sizeof(*fnp2));    if ((fnp != (f_node_ptr) 0)        && (i != fd)        && (fnp->f_count > 0) && (is_same_file(fnp, fnp2)))    {      if (collect)      {        /* We're collecting file changes from any other           f_node which refers to this file. */        if (fnp2->f_mode != RDONLY)        {          copy_file_changes(fnp2, fnp);          break;        }      }      else      {        /* We just made changes to this file, so we are           distributing these changes to the other f_nodes           which refer to this file. */        copy_file_changes(fnp, fnp2);        fmemcpy(&f_nodes[i], fnp2, sizeof(*fnp2));      }    }  }  release_near_f_node(fnp2);}    /* /// Added - Ron Cemer */STATIC int is_same_file(f_node_ptr fnp1, f_node_ptr fnp2){  return      (fnp1->f_dpb->dpb_unit == fnp2->f_dpb->dpb_unit)      && (fnp1->f_dpb->dpb_subunit == fnp2->f_dpb->dpb_subunit)      && (fcbmatch(fnp1->f_dir.dir_name, fnp2->f_dir.dir_name))      && ((fnp1->f_dir.dir_attrib & D_VOLID) == 0)      && ((fnp2->f_dir.dir_attrib & D_VOLID) == 0)      && (fnp1->f_diroff == fnp2->f_diroff)      && (fnp1->f_dirstart == fnp2->f_dirstart)      && (fnp1->f_dpb == fnp2->f_dpb);}    /* /// Added - Ron Cemer */STATIC void copy_file_changes(f_node_ptr src, f_node_ptr dst){  dst->f_dir.dir_start = src->f_dir.dir_start;#ifdef WITHFAT32  dst->f_dir.dir_start_high = src->f_dir.dir_start_high;#endif  dst->f_dir.dir_size = src->f_dir.dir_size;  dst->f_dir.dir_date = src->f_dir.dir_date;  dst->f_dir.dir_time = src->f_dir.dir_time;}STATIC COUNT delete_dir_entry(f_node_ptr fnp){  COUNT rc;  /* Ok, so we can delete. Start out by           */  /* clobbering all FAT entries for this file     */  /* (or, in English, truncate the FAT).          */  if ((rc = remove_lfn_entries(fnp)) < 0)    return rc;  wipe_out(fnp);  *(fnp->f_dir.dir_name) = DELETED;  /* The directory has been modified, so set the  */  /* bit before closing it, allowing it to be     */  /* updated                                      */  fnp->f_flags |= F_DMOD;  dir_close(fnp);  /* SUCCESSful completion, return it             */  return SUCCESS;}COUNT dos_delete(BYTE * path, int attrib){  REG f_node_ptr fnp;  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(path, fcbname)) == NULL)  {    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, attrib))  {    /* Do not delete directories or r/o files       */    /* lfn entries and volume labels are only found */    /* by find_fname() if attrib is set to a        */    /* special value                                */	      if (fnp->f_dir.dir_attrib & (D_RDONLY | D_DIR))    {      dir_close(fnp);      return DE_ACCESS;    }    return delete_dir_entry(fnp);  }  else  {    /* No such file, return the error               */    dir_close(fnp);    return DE_FILENOTFND;  }}COUNT dos_rmdir(BYTE * path){  REG f_node_ptr fnp;  REG f_node_ptr fnp1;  BOOL found;  char fcbname[FNAME_SIZE + FEXT_SIZE];  /* prevent removal of the current directory of that drive */  register struct cds FAR *cdsp = get_cds(path[0] - 'A');  if (!fstrcmp(path, cdsp->cdsCurrentPath))    return DE_RMVCUDIR;  /* next, split the passed dir into components (i.e. -   */  /* path to new directory and name of new directory      */  if ((fnp = split_path(path, fcbname)) == NULL)  {    return DE_PATHNOTFND;  }  /* Check that we're not trying to remove the root!      */  if ((path[0] == '\\') && (path[1] == NULL))  {    dir_close(fnp);    return DE_ACCESS;  }  /* Verify name exists, and if so then ensure it refers  */  /* to a directory and directory is empty.               */  if (find_fname(fnp, fcbname, D_ALL))  {    /* Check if it's really a directory, directories may       have attributes, but if other than 'archive' then do not       allow (RDONLY|SYSTEM|HIDDEN) directory to be deleted.    */    if ( !(fnp->f_dir.dir_attrib & D_DIR) ||          (fnp->f_dir.dir_attrib & ~(D_DIR |D_ARCHIVE)) )    {      dir_close(fnp);      return DE_ACCESS;    }    /* Check that the directory is empty. Only the  */    /* "." and ".." are permissable.                */    fnp->f_flags &= ~F_DMOD;    fnp1 = dir_open(path);    if (fnp1 == NULL)    {      dir_close(fnp);      return DE_ACCESS;    }        dir_read(fnp1);    /* 1st entry should be ".", else directory corrupt or not empty */    if (fnp1->f_dir.dir_name[0] != '.' || fnp1->f_dir.dir_name[1] != ' ')    {      dir_close(fnp);      return DE_ACCESS;    }    fnp1->f_diroff++;    dir_read(fnp1);    /* secondard entry should be ".." */    if (fnp1->f_dir.dir_name[0] != '.' || fnp1->f_dir.dir_name[1] != '.')    {      dir_close(fnp);      return DE_ACCESS;    }    /* Now search through the directory and make certain    */    /* that there are no entries.                           */    found = FALSE;    fnp1->f_diroff++;    while (dir_read(fnp1) == 1)    {      if (fnp1->f_dir.dir_name[0] == '\0')        break;      if (fnp1->f_dir.dir_name[0] != DELETED          && fnp1->f_dir.dir_attrib != D_LFN)      {        found = TRUE;        break;      }      fnp1->f_diroff++;    }    dir_close(fnp1);    /* If anything was found, exit with an error.   */    if (found)    {      dir_close(fnp);      return DE_ACCESS;    }    return delete_dir_entry(fnp);  }  else  {    /* No such file, return the error               */    dir_close(fnp);    return DE_FILENOTFND;  }}COUNT dos_rename(BYTE * path1, BYTE * path2, int attrib){  REG f_node_ptr fnp1;  REG f_node_ptr fnp2;  COUNT ret;  char fcbname[FNAME_SIZE + FEXT_SIZE];  /* prevent renaming of the current directory of that drive */  register struct cds FAR *cdsp = get_cds(path1[0] - 'A');  if (!fstrcmp(path1, cdsp->cdsCurrentPath))    return DE_RMVCUDIR;  /* first split the passed target into compnents (i.e. - path to */  /* new file name and name of new file name                      */  if ((fnp2 = split_path(path2, fcbname)) == NULL)  {    return DE_PATHNOTFND;  }  /* Check that we don't have a duplicate name, so if we find     */  /* one, it's an error.                                          */  if (find_fname(fnp2, fcbname, attrib))  {    dir_close(fnp2);    return DE_ACCESS;  }  /* next split the passed source into compnents (i.e. - path to  */  /* old file name and name of old file name                      */  if ((fnp1 = split_path(path1, fcbname)) == NULL)  {    dir_close(fnp2);    return DE_PATHNOTFND;  }  if (!find_fname(fnp1, fcbname, attrib))  {    /* No such file, return the error                       */    dir_close(fnp1);    dir_close(fnp2);    return DE_FILENOTFND;  }  ret = alloc_find_free(fnp2, path2, fcbname);  if (ret != SUCCESS) {    dir_close(fnp1);    return ret;  }  if ((ret = remove_lfn_entries(fnp1)) < 0)    return ret;  /* init fnode for new file name to match old file name */  memcpy(&fnp2->f_dir, &fnp1->f_dir, sizeof(struct dirent));  /* put the fnode's name into the directory.                     */  memcpy(fnp2->f_dir.dir_name, fcbname, FNAME_SIZE + FEXT_SIZE);  /* The directory has been modified, so set the bit before       */  /* closing it, allowing it to be updated.                       */  fnp1->f_flags = fnp2->f_flags = F_DMOD | F_DDIR;  /* Ok, so we can delete this one. Save the file info.           */  *(fnp1->f_dir.dir_name) = DELETED;  dir_close(fnp1);  dir_close(fnp2);  /* SUCCESSful completion, return it                             */  return SUCCESS;}/*                                                              *//* wipe out all FAT entries starting from st for create, delete, etc. *//*                                                              */STATIC VOID wipe_out_clusters(struct dpb FAR * dpbp, CLUSTER st){  REG CLUSTER next;  /* Loop from start until either a FREE entry is         */  /* encountered (due to a fractured file system) of the  */  /* last cluster is encountered.                         */  while (st != LONG_LAST_CLUSTER)  {    /* get the next cluster pointed to              */    next = next_cluster(dpbp, st);    /* just exit if a damaged file system exists    */    if (next == FREE || next == 1)      return;    /* zap the FAT pointed to                       */    link_fat(dpbp, st, FREE);    /* and the start of free space pointer          */#ifdef WITHFAT32    if (ISFAT32(dpbp))    {      if ((dpbp->dpb_xcluster == UNKNCLUSTER) || (dpbp->dpb_xcluster > st))        dpbp->dpb_xcluster = st;    }    else#endif    if ((dpbp->dpb_cluster == UNKNCLUSTER) || (dpbp->dpb_cluster > st))      dpbp->dpb_cluster = (UWORD)st;    /* and just follow the linked list              */    st = next;  }#ifdef WITHFAT32  if (ISFAT32(dpbp))    write_fsinfo(dpbp);#endif}/*                                                              *//* wipe out all FAT entries for create, delete, etc.            *//*                                                              */STATIC VOID wipe_out(f_node_ptr fnp){  /* if not already free and valid file, do it */  if (fnp && !checkdstart(fnp->f_dpb, &fnp->f_dir, FREE))  wipe_out_clusters(fnp->f_dpb, getdstart(fnp->f_dpb, &fnp->f_dir));}STATIC BOOL find_free(f_node_ptr fnp){  COUNT rc;  while ((rc = dir_read(fnp)) == 1)  {    if (fnp->f_dir.dir_name[0] == DELETED)      return TRUE;    fnp->f_diroff++;  }  return rc >= 0;}/* alloc_find_free: resets the directory by a close followed by   *//* an open. Then finds a spare directory entry and if not         *//* available, tries to extend the directory.                      */STATIC int alloc_find_free(f_node_ptr fnp, char *path, char *fcbname){  fnp->f_flags &= ~F_DMOD;  dir_close(fnp);  fnp = split_path(path, fcbname);  /* Get a free f_node pointer so that we can use */  /* it in building the new file.                 */  /* Note that if we're in the root and we don't  */  /* find an empty slot, we need to abort.        */  if (find_free(fnp) == 0)  {    if (fnp->f_dirstart == 0)    {      fnp->f_flags &= ~F_DMOD;      dir_close(fnp);      return DE_TOOMANY;    }    else    {      /* Otherwise just expand the directory          */      int ret;      if ((ret = extend_dir(fnp)) != SUCCESS)        /* fnp already closed in extend_dir */        return ret;    }  }  return SUCCESS;}/*                                                              *//* dos_getdate for the file date                                *//*                                                              */date dos_getdate(void){  struct dosdate dd;  /* First - get the system date set by either the user   */  /* on start-up or the CMOS clock                        */  DosGetDate(&dd);  return DT_ENCODE(dd.month, dd.monthday, dd.year - EPOCH_YEAR);}/*                                                              *//* dos_gettime for the file time                                *//*                                                              */time dos_gettime(void){  struct dostime dt;  /* First - get the system time set by either the user   */  /* on start-up or the CMOS clock                        */  DosGetTime(&dt);  return time_encode(&dt);}/*                                                              *//* dos_getftime for the file time                               */

⌨️ 快捷键说明

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