Skip to content

更新文件属性

李述铜

1311字约4分钟

2024-08-08

提示

同学,你好,欢迎学习本课程!本课程是介绍了FATFS文件系统模块的基本使用,是一门相对较简单的课程。

如果你对文件系统的实现比较感兴趣,也可以关注我的《从0到1写FAT32文件系统》课程。

欢迎转载本文章,转载请注明链接来源,谢谢!

本小节介绍文件属性更改的接口,Linux及标准库下相关的接口有:

应用场合

在少数情况下,需要修改文件或目录的属性,例如文件名、只读、隐藏、时间戳等。FATFS提供了相应的接口来修改这些属性。

接口介绍

修改名称

f_rename函数可以用于对文件或目录的名称修改,也可以用于将文件或目录移动到其它某个目录下

FRESULT f_rename(
  const TCHAR* old_name, /* [IN] 旧对象名称 */
  const TCHAR* new_name  /* [IN] 新对象名称 */
);

函数参数:

  • old_name:文件或目录所在的路径,可使用绝对或相对路径
  • new_name:文件或目录新的名称或路径

返回值:

  • FR_OK:操作成功。
  • FR_DISK_ERR:磁盘操作错误。
  • FR_INT_ERR:FatFs 内部错误。
  • FR_NOT_READY:物理驱动器未准备好。
  • FR_NO_FILE:未找到文件。
  • FR_NO_PATH:无法找到路径。
  • FR_INVALID_NAME:无效的路径或文件名。
  • FR_EXIST:新对象名称已存在。
  • FR_WRITE_PROTECTED:磁盘为只读。
  • FR_INVALID_DRIVE:无效的逻辑驱动器。
  • FR_NOT_ENABLED:文件系统未启用。
  • FR_NO_FILESYSTEM:没有文件系统。
  • FR_TIMEOUT:操作超时。
  • FR_LOCKED:文件已被锁定。
  • FR_NOT_ENOUGH_CORE:内存不足。

示例:

/* 在默认驱动器中重命名对象 */
f_rename("oldname.txt", "newname.txt");

/* 在第二个驱动器中重命名对象 */
f_rename("2:oldname.txt", "newname.txt");

/* 重命名对象并将其移动到驱动器中的另一个目录 */
f_rename("log.txt", "old/log0001.txt");

修改属性标志

在FAT文件系统中,文件或目录可具备一定的属性,如只读、存档、系统、隐藏等。一般情况下,我们不需要修改这些属性,直接使用创建文件时自带的默认属性即可。但在某些情况下,我们可能需要修改属性,此时可以使用f_chmode(change mode)接口来实现这个需求。

FRESULT f_chmod (
  const TCHAR* path, /* [IN] 对象名称 */
  BYTE attr,         /* [IN] 属性标志 */
  BYTE mask          /* [IN] 属性掩码 */
);

参数:

  • path:目录或者文件的路径。
  • attr:要设置的属性标志,可以是以下一个或多个组合:AM_RDO(只读)、AM_ARC(存档)、AM_SYS(系统)、AM_HID(隐藏)。
  • mask:属性掩码,指定要更改的属性。指定的属性将被设置或清除,而其他属性将保持不变。

返回值:

  • FR_OK:操作成功。
  • FR_DISK_ERR:磁盘操作错误。
  • FR_INT_ERR:FatFs 内部错误。
  • FR_NOT_READY:物理驱动器未准备好。
  • FR_NO_FILE:未找到文件。
  • FR_NO_PATH:无法找到路径。
  • FR_INVALID_NAME:无效的路径或文件名。
  • FR_WRITE_PROTECTED:磁盘为只读。
  • FR_INVALID_DRIVE:无效的逻辑驱动器。
  • FR_NOT_ENABLED:文件系统未启用。
  • FR_NO_FILESYSTEM:没有文件系统。
  • FR_TIMEOUT:操作超时。
  • FR_NOT_ENOUGH_CORE:内存不足。

示例:

/* 设置为只读,清除存档属性,其他属性保持不变 */
f_chmod("file.txt", AM_RDO, AM_RDO | AM_ARC);

上述代码中,指定了要修改AM_RDO | AM_ARC和两个属性位,由于attr参数=AM_RDO,即表明要将ReadOnly位置1;而另一个位AM_ARC位由于没有在该参数中,所以表示其要清除AM_ARC位。

通过attr和mode的组合,即可使用指定要修改哪些属性标志,并且这些属性标志中哪些清0哪些置1。

修改文件时间戳

一般情况下,文件或目录的修改时间会随着文件的写入自动更新,无需处理。如果必须要自己修改文件的时间,可以使用f_utime()函数。

FRESULT f_utime (
  const TCHAR* path,  /* [IN] 对象名称 */
  const FILINFO* fno  /* [IN] 要设置的时间和日期 */
);

参数:

  • path:指向以 null 结尾的字符串,指定要更改时间戳的对象。
  • fno:指向文件信息结构的指针,其中包含要在 fdateftime 成员中设置的时间戳。不需要关心其他成员。

返回值:

  • FR_OK:操作成功。
  • FR_DISK_ERR:磁盘操作错误。
  • FR_INT_ERR:FatFs 内部错误。
  • FR_NOT_READY:物理驱动器未准备好。
  • FR_NO_FILE:未找到文件。
  • FR_NO_PATH:无法找到路径。
  • FR_INVALID_NAME:无效的路径或文件名。
  • FR_WRITE_PROTECTED:磁盘为只读。
  • FR_INVALID_DRIVE:无效的逻辑驱动器。
  • FR_NOT_ENABLED:文件系统未启用。
  • FR_NO_FILESYSTEM:没有文件系统。
  • FR_TIMEOUT:操作超时。
  • FR_NOT_ENOUGH_CORE:内存不足。

示例: 下面是一个示例函数,用于设置文件或子目录的时间戳:

FRESULT set_timestamp (
    char *obj,     /* 文件名的指针 */
    int year,
    int month,
    int mday,
    int hour,
    int min,
    int sec
)
{
    FILINFO fno;

    fno.fdate = (WORD)(((year - 1980) * 512U) | month * 32U | mday);
    fno.ftime = (WORD)(hour * 2048U | min * 32U | sec / 2U);

    return f_utime(obj, &fno);
}

从上面的代码可以看到,虽然f_tuime传入了整个FILINFO结构,但实际上这个结构中使用的只是fdate和ftime两个字段,其它内容并不会影响。所以不需要对其它字段进行任何初始化设置。