文件与目录
常用函数
stat()
int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
- 功能: 返回一个与pathname 或fd 指定的文件属性信息,存储在结构体buf,lstat函数类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。
- 返回: 若成功则为0 ,若出错则为-1
access()
- int access(const char *pathname, int mode);
- 功能: 检查是否可以对指定文件进行某种操作,即检查文件访问的权限mode
- R_OK 判断文件是否有读权限
- W_OK 判断文件是否有写权限
- X_OK 判断文件是否有可执行权限
- F_OK 判断文件是否存在
- 返回:成功执行时返回0 ,若出错为-1
umask()
- mode_t umask(mode_t mode);
- 功能:为进程设置文件方式创建屏蔽字,并返回以前的值
- 返回:以前的文件模式创建屏蔽字
chmod()
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
- 功能:更改现存文件的权限。chmod函数在指定的文件上进行操作,而fchmod则对已打开的文件进行操作。
- 返回:成功返回0 ,出错返回-1
truncate()
int truncate(const char *pathname, off_t length);
int ftruncate(int fd, off_t length);
- 功能:文件截短,length:文件截短后的长度
- 返回:成功返回0 ,出错返回-1
utime()
- int utime(const char *pathname, const struct utimbuf *times);
- 功能:更改文件的存取和修改时间
- 返回:成功返回0 ,出错返回-1
struct utimbuf {
time_t actime; /* access time */
time_t modtime; /* modification time */
};
字段 | 说明 | 例子 | ls 选项 |
---|---|---|---|
st_atime | 文件数据最后访问时间 | read | -u |
st_mtime | 文件数据最后修改时间 | write | 默认 |
st_ctime | i 节点最后更改时间 | chmod, chown | -c |
link()
- int link(const char *existingpath, const char *newpath);
- 功能: 创建一个指向现存文件连接( 硬链接),类似与linux系统的ln
- 返回: 成功返回0 ,出错返回-1
- int unlink(const char *pathname);
- 功能: 删除pathname 指定的硬链接,并将由pathname所引用的文件链接计数减1
- 返回: 成功返回0 ,出错返回-1
- 硬链接创建条件
- 针对文件创建链接
- 必须是同一个分区
- 只用超级用户才能对目录建立链接
- 文件删除条件
- 链接计数为0
- 无其他进程打开该文件
remove() 与 rename()
- int remove(const char *pathname);
- 功能: 解除对一个文件或目录的连接
- 返回: 成功返回0 ,出错返回-1
- int rename(const char *oldname, const char *newname);
- 功能: 文件或目录更名
- 返回: 成功返回0 ,出错返回-1
- 对于文件,remove的功能与unlink相同。
- 对于目录,remove的功能与rmdir相同。
symlink() 与 readink()
- int symlink(const char *actualpath, const char *sympath);
- 功能: 创建一个符号连接( 软连接),与linux系统的ln -s类似
- 返回: 成功返回0 ,出错返回-1
- int readlink(const char *restrict pathname,char *restrict buf, size_t bufsize);
- 功能: 打开该连接本身,并读该链接中的名字。
- 返回: 成功返回读到的字节数,出错返回-1
- 符号链接创建
- 创建符号链接并不要求actualpath存在
- 可以跨文件系统建立符号链接
目录操作
mkdir() 与 rmdir
- int mkdir(const char *pathname, mode_t mode);
- 功能: 创建目录
- 返回: 成功返回0 ,出错返回-1
- int rmdir(const char *pathname);
- 功能: 删除目录
- 返回: 成功返回0 ,出错返回-1
opendir(), readdir(), rewinddir(), closedir()
- DIR *opendir(const char *pathname);
- 功能: 打开目录
- 返回: 成功返回目录指针,出错返回NULL
- struct dirent *readdir(DIR *dp);
- 功能: 读取目录
- 返回: 成功返回指针,若在目录结尾或者出错返回NULL
- void rewinddir(dir(DIR *dp);
- 功能: 重新定位从头开始读取
- 返回: 成功返回0 ,出错返回-1
- int closedir(DIR *dp);
- 功能: 关闭目录
- 返回: 成功返回0 ,出错返回-1
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported by all file system types */
char d_name[256]; /* filename */
};
d_type表示档案类型:
类型 | 英文说明 | 中文说明 |
---|---|---|
DT_BLK | This is a block device. | 块设备文件 |
DT_CHR | This is a character device. | 字符设备文件 |
DT_DIR | This is a directory. | 普通目录 |
DT_FIFO | This is a named pipe (FIFO). | 命名管道或FIFO |
DT_LNK | This is a symbolic link. | 链接文件 |
DT_REG | This is a regular file. | 普通文件 |
DT_SOCK | This is a UNIX domain socket. | 本地套接口 |
DT_UNKNOWN | The file type is unknown. | 未知的类型 |
enum{
DT_UNKNOWN = 0,
# define DT_UNKNOWN DT_UNKNOWN
DT_FIFO = 1,
# define DT_FIFO DT_FIFO
DT_CHR = 2,
# define DT_CHR DT_CHR
DT_DIR = 4,
# define DT_DIR DT_DIR
DT_BLK = 6,
# define DT_BLK DT_BLK
DT_REG = 8,
# define DT_REG DT_REG
DT_LNK = 10,
# define DT_LNK DT_LNK
DT_SOCK = 12,
# define DT_SOCK DT_SOCK
DT_WHT = 14
# define DT_WHT DT_WHT
};
获取地址
int chdir(const char *pathname);
int fchdir(int fd);
- 功能: 分别用pathname 或fd 来指定新的当前工作目录
- 返回: 成功返回0 ,出错返回-1
- char *getcwd(char *buf, size_t size);
- 功能: 获得当前工作目录的绝对路径名,类似与linux的pwd
- 返回: 成功返回buf ,出错返回NULL
函数详解
stat函数
- 包含在struct stat中,可以通过stat函数获得:
struct stat{
mode_t st_mode; /file type & permission/
ino_t st_ino; /i-node number/
dev_t st_dev; /device number (file system)/
dev_t st_rdev; /device number for special files/
nlink_t st_nlink; /number of links/
uid_t st_uid; /user ID of owner/
gid_t st_gid; /group ID of owner/
off_t st_size; /size in bytes/
time_t st_atime; /time of last access/
time_t st_mtime; /time of last modification/
time_t st_ctime; /time of last file status change/
blksize_t st_blksize; /best I/O block size/
blkcnt_t st_blocks; /number of disk blocks allocated/
};
- 文件类型,通过调用文件类型判断宏运算文件属性结构体中的st_mode获得文件类型
- 普通文件(regular file) S_ISREG()
- 目录文件(directory file) S_ISDIR()
- 块特殊文件(block special file) S_ISBLK()
- 字符特殊文件(chatacter special file) S_ISCHR()
- FIFO(named pipe) S_ISFIFO()
- 套接字(socket) S_ISSOCK()
- 符号链接(symbolic link) S_ISLNK()
- 文件权限,文件权限通过按位或方式构造,有9种文件访问权限位
- 用户权限:S_IRUSR, S_IWUSR, S_IXUSR
- 组权限:S_IRGRP, S_IWGRP, S_IXGRP
- 其它权限:S_IROTH, S_IWOTH, S_IXOTH
- 程序示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
void show_time(time_t t)
{
struct tm* p = NULL;
p = localtime(&t);
printf("%d-%d-%d %d:%d:%d\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,\
p->tm_hour,p->tm_min,p->tm_sec);
}
int main(int argc,char *argv[])
{
//1.参数验证
if (argc != 2){
perror("输入的参数错误!");
exit(1);
}
//2.获取文件属性
struct stat buf;
memset(&buf,0,sizeof(buf));
if(stat(argv[1],&buf) < 0){
printf("%s",strerror(errno));
exit(-1);
}
//3.判断文件类型
if(S_ISREG(buf.st_mode))
printf("%s file mode is %s\n",argv[1],"普通文件");
if(S_ISDIR(buf.st_mode))
printf("%s file mode is %s\n",argv[1],"目录文件");
if(S_ISBLK(buf.st_mode))
printf("%s file mode is %s\n",argv[1],"快特殊文件");
if(S_ISCHR(buf.st_mode))
printf("%s file mode is %s\n",argv[1],"字符特殊文件");
if(S_ISFIFO(buf.st_mode))
printf("%s file mode is %s\n",argv[1],"FIFO(named pipe)");
if(S_ISSOCK(buf.st_mode))
printf("%s file mode is %s\n",argv[1],"套接字(socket)");
if(S_ISLNK(buf.st_mode))
printf("%s file mode is %s\n",argv[1],"符号链接");
//4.文件inode,UID,Time of last acess
printf("inode:%ld\nUID:%d\n",buf.st_ino,buf.st_uid);
printf("time of last acess:");
show_time(buf.st_atime);
return 0;
}
chmod函数权限
- mode:文件权限(按位或操作)
- S_ISUID, S_ISGID, S_ISVTX
- S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR
- S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP
- S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc ,char *argv[])
{
if(argc < 2){
perror("参数不对\n");
exit(1);
}
if(access(argv[1],F_OK) == 0){
perror("文件已存在\n");
exit(1);
}
mode_t save_mask=umask(0555);
int fp = open(argv[1],O_RDWR|O_CREAT,0613);
if(fp < 0){
perror("打开文件失败\n");
exit(1);
}
struct stat buff;
if(stat(argv[1],&buf) == -1){
perror("get informaintion of file fail");
exit(1);
}
if(access(argv[1],W_OK) == -1){
perror("文件没有写权限\n");
}
else{
if(chmod(argv[1],buf.st_mode & (~S_IWUSR)) == -1){
perror("更改失败\n");
exit(1);
}
}
umask(save_mask);
close(fp);
return 0;
}
access与umask函数示例
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int main(void)
{
int save_mask = umask(0333);
int fd = creat("pig.txt",0777);
if(access("pig.txt",F_OK) < 0){
perror("creat file fail");
}
system("touch 1.c");
umask(save_mask);
return 0;
}
utime函数示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <utime.h>
void show_time(time_t t)
{
struct tm* p = NULL;
p = localtime(&t);
printf("%d-%d-%d %d:%d:%d\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,\
p->tm_hour,p->tm_min,p->tm_sec);
}
int main(int argc,char *argv[])
{
if(argc != 2){
perror("参数不对!");
exit(-1);
}
struct stat buf;
struct stat save_buf;
memset(&buf,0,sizeof(buf));
memset(&save_buf,0,sizeof(save_buf));
if(lstat(argv[1],&buf) < 0){
printf("%s\n",strerror(errno));
exit(0);
}
save_buf = buf;
printf("time of last access:");
show_time(buf.st_atime);
printf("time of last modification:");
show_time(buf.st_mtime);
sleep(3);
int fd = open(argv[1],O_RDWR);
char buffer[1024] = " ";
read(fd,buffer,1024);
write(fd,"hello world\n",sizeof("hello world\n"));
sleep(3);
memset(&buf,0,sizeof(buf));
if(lstat(argv[1],&buf) < 0){
printf("%s\n",strerror(errno));
exit(0);
}
printf("time of last access:");
show_time(buf.st_atime);
printf("time of last modification:");
show_time(buf.st_mtime);
close(fd);
struct utimbuf ubuf;
ubuf.actime = save_buf.st_atime;
ubuf.modtime = save_buf.st_mtime;
sleep(3);
if(utime(argv[1],&ubuf) < 0){
perror("modfiy time fail\n");
exit(1);
}
memset(&buf,0,sizeof(buf));
if(lstat(argv[1],&buf) < 0){
printf("%s\n",strerror(errno));
exit(0);
}
printf("time of last access:");
show_time(buf.st_atime);
printf("time of last modification:");
show_time(buf.st_mtime);
return 0;
}
目录操作,实现ls -R的功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
void List(char *path)
{
struct dirent *file = NULL;
DIR *pDir;
char fileName[256][256];
int i = 0, len = 0;
if((pDir = opendir(path)) != NULL){
while(NULL != (file = readdir(pDir))){
if(strcmp(file->d_name,".") == 0){ //排除隐藏目录
printf(". ");
continue;
}
else if(strcmp(file->d_name,"..") == 0){
printf(".. ");
continue;
}
else if(file->d_type == DT_DIR){ //查找到子目录并将其放在数组fileName中
printf("\033[32;49m%s \033[0m", file->d_name);
sprintf(fileName[len++],"%s%s%s",path,"/",file->d_name);
}
else{
printf("%s ", file->d_name);
}
}
printf("\n\n");
for(i=0 ; i < len ; ++i){
printf("%s:\n",fileName[i]); //递归调用显示子目录内容
List(fileName[i]);
}
closedir(pDir);
}
else{
printf("Open Dir-[%s] failed.\n\n", path);
}
}
int main(int argc,char *argv[])
{
char buf[256] = " ";
int i = 0;
if(argc < 2){ //入参判断
getcwd(buf,sizeof(buf));
List(buf);
}
else{
for(i=1 ; i < argc ; ++i){
List(argv[i]);
}
}
return 0;
}