LInux下文件编程(2)

在上一篇文章中讲解了linux中文件编程的基本函数,在这儿将继续讲解一些比较高级的文件编程

1  确定和改变文件模式

1.1 umask 函数

       通过ls -l 命令可以察看一个文件或者一个文件夹的属性,其中在我的电脑运行ls -l 3-1.c就有如下结果:

       

其中,最开始的1-10个字符表示所有者、所属组、其他人的读写执行权限,通常通过4,2,1来表示读、写、执行的权限,例如6=4+2 表示具有读写权限,不具有执行权限。

在文件中具有一个文件屏码,称为umask,在终端中输入umask,有如下结果:

       

即在linux中默认的umask为0002

在命令行中如果想要改umask的数值,那么就在终端中输入:umask+新数值即可。当然也可以通过函数来改变。格式如下:

    #include<sys/stat.h>
    mode_t umask( mode_t mask )

cmaks表示新设置的文件创建屏蔽码,返回值为原来的umask值

例如:creat("tz.txt",0777);如果此时的umaks=042,那么此时的tz.txt的权限为0735


1.2 chmod 和fchmod 函数

    #include<sys/stat.h>
    int chmod( const char *pathname, mode_t mode );
    int fchmod( int fd, mode_t mode );

    功能:改变一个文件的存取权限

    备注:要改变一个文件的访问权限位,进程的有效用户ID必须等于文件所有者的用户ID,或者该进程具有超级用户权限。

    参数说明:pathname表示指定的文件名,mode表示新的文件权限,fd表示一个文件描述符。

    返回值:成功返回0,反之返回-1


1.3 chown和fchown 函数

    在umask函数那么通过ls -l 3-1.c可以可知3-1.c的所有者和所属组,即1后面的ricklu

    功能:改变文件或者路径的所属组和所有者

    格式:#include<unistd.h>

              int chown( const char *pathname, uid_t owner, gid_t group );
              int fchown( int fd, uid_t owner, gid_t group );

    参数:pathname表示文件名或者路径名的指针,owner表示改变后的所有者,group表示改变后的所属组

    备注:只有root用户才可以使用这两个函数改变任意一个文件的所有者和所属组,普通用户只能改变自己所有的文件的组识别号,且只能在其所属组中进行选择。


1.4 rename 函数

    功能:对一个文件重命名

    格式:#include<stdio.h>

              int rename(const char *oldname,const char *newname)

    参数:分别表示旧文件名和新文件名

    返回值:成功返回0,反之返回-1


1.5 truncate和ftruncate 函数

    功能:对文件的大小进行修改,截断文件长度。

    格式:#include<unistd.h>
              int truncate( const char *pathname, off_t length );
              int ftruncate( int fd, off_t length );

    参数:pathname和fd同上,length表示将文件截取到的长度-文件的新长度

    返回值:成功返回0,反之返回-1


1.6 access 函数

    功能:以实际用户ID和实际组ID测试访问权限

    格式:#include<unistd.h>
              int access( const char *pathname, int mode );

    参数:pathname同上,mode表示待测试的权限

    返回值:成功返回0,反之返回-1

    说明:mode可以取如下的值从而对因测试权限,通过|来决定mode的值

              R_OK 测试读权限
              W_OK 测试写权限
              X_OK 测试执行权限
              F_OK 测试文件是否存在

     例子:access(“tz.txt”,06)测试tz.txt是否具有读写权限

               access(“tz”,F_OK) 测试tz是否存在


2  查询文件信息

     对于一个文件而言,它的详细信息都是存储在stat这一个结构体中,通过stat中不同的数值可以获得不同的信息,因此获取文件信息的核心就是struct stat

2.1 stat 和fstat和lstat 函数

     功能:获取文件相关的信息结构填入由指针buf指向的stat结构中

     格式:#include<sys/stat.h>
               int stat( const char *restrict pathname, struct stat *restrict buf );
               int lstat( const char *restrict pathname, struct stat *restrict buf );
               int fstat( int fd, struct stat *buf );

     参数:pathname同上,buf表示stat的指针,用来存储文件或者路径的相关信息

     返回值:成功返回0,反之返回-1

     备注:可以通过mode&S_IFMT的结果来检测文件类型,在这儿会用一个例子来说明


2.2 utime 和utimes 函数

      每个文件都有三个时间戳关联:最近访问时间、最近修改时间和最近特性修改时间,它们分别对应stat中的st_atime、st_mtime和st_ctime。在这儿它们都是time_t类型,定义在<time.h>。可以通过函数来改变一个文件的最近访问时间和最近修改时间,但是不能修改最近特性修改时间,因为i节点由系统来维护。

       功能:修改文件的访问时间和修改时间

       格式:#include<utime.h>
                   int utime( const char *pathname, cosnt struct utimebuf *times );
                   int utimes( const char *pathname, cosnt struct timeval values[2] );

       参数:pathname表示要更新时间的文件或者路径 ,utimebuf表示一个时间结构体,values[0]和values[1]分别表示指定文件的访问时间和修改时间。

       返回值:成功返回0,并更新st_ctime,失败返回-1

       说明:utimebuf结构和 timeval结构

                   struct utimebuf
                   {
                           time_t actime; //访问时间
                           time_t modtime; //修改时间
                   }

                  struct timeval

                  {

                           long tv_sec;//自公元纪年来的秒数

                           long tv_usec;//秒后的微秒数

                  }

        特别注意:此函数的操作及执行它所要求的特权取决于times参数是否为NULL:
        1 如果times是NULL,则访问时间和修改时间都设置为当前时间,执行此操作必须满足:进程的有效用户ID和该文件的所有者ID必须相等,或者进程对该文件必须具有写权限。
        2 如果times非NULL,则访问时间和修改时间都设置为times所指向结构中的值,执行此操作必须满足:进程的有效用户ID和该文件的所有者ID必须相等,或者进程是超级进程,对文件仅有写权限是不够的。

在这儿通过如上介绍,来判断一个文件的类型

#include<sys/stat.h>
#include<sys/types.h>
#include<utime.h>
#include<fcntl.h>
#include<stdio.h>

int main(int argc,char *argv[])
{
    int i;
    struct stat buf;
    char *ptr;

    for(i=1;i<argc;i++)
    {
        printf("%s: ",argv[i]);
        if(lstat(argv[i],&buf)<0)
        {
            perror("error\n");
            continue;
        }

        switch(S_IFMT&buf.st_mode)
        {
            case S_IFREG:ptr="常规文件";break;
            case S_IFDIR:ptr="目录文件";break;
            case S_IFCHR:ptr="字符设备文件";break;
            case S_IFBLK:ptr="块设备文件";break;
            case S_IFIFO:ptr="管道文件";break;
            case S_IFLNK:ptr="符号链接文件";break;
            case S_IFSOCK:ptr="套借字文件";break;
            default:ptr="未知文件";break;
        }
        printf("%s\n",ptr);
    }
    return 0;
}
打开一个文件,将他截断至0长度,但维持他的访问时间和修改时间不变

#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<utime.h>

int main(int argc,char *argv[])
{
    struct stat statbuf;//保存时间的结构体
    struct utimbuf times;//设置时间的结构体
    int i,fd;

    if(argc!=2)
    {
        printf("参数错误\n");
        return 1;
    }

    if((fd=open(argv[1],O_RDWR))==-1)
    {
        printf("打开文件失败\n");
        return 2;
    }

    if(stat(argv[1],&statbuf)<0)
    {
        return 2;
    }

    if(ftruncate(fd,0)<0)
    {
        printf("截断文件长度失败\n");
        return 3;
    }

    printf("%s is ftruncate now\n",argv[1]);
    times.actime=statbuf.st_atime;
    times.modtime=statbuf.st_mtime;

    if(utime(argv[1],×)==0)
        printf("时间修改成功\n");
    else
        printf("时间修改失败\n");

    close(fd);
    return 0;
}
2.3 文件长度

      文件长度由stat结构成员st_size表示,以字节为单位,此字段只对普通文件、目录文件和符号链接有意义。


3 文件其他操作

3.1 dup和dup2 函数

      功能:复制文件描述符

      格式:#include<unistd.h>

                  int dup( int oldfd );

                  int dup2( int oldfd, int newfd);

      参数:oldfd和newfd分别表示旧文件描述符和新文件描述符

      返回值:成功返回新的文件描述符,出错返回-1

      说明:dup一定返回当前可用的最小文件描述符; dup2指定参数newfd为新的文件描述符,当newfd打开时,先将其关闭,若oldfd和newfd相等,返回newfd而不关闭它。

#include<sys/stat.h>
#include<utime.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdio.h>

int main(int argc,char *argv[])
{
    int fd;

    if(argc<2)
    {
        printf("参数错误\n");
        return 1;
    }

    if((fd=open(*(argv+1),O_CREAT|O_WRONLY,0644))==-1)
    {
        printf("打开文件出错\n");
        return 2;
    }

    if(dup2(fd,STDOUT_FILENO)==-1)
    {
        printf("文件重定向出错\n");
        return 3;
    }

    printf("dup2 successed!\n");
    close(fd);
    return 0;
}


3.2 fcntl 函数

      fcntl代表对文件控制,他提供了进一步管理低级文件描述符的各种手段,用它可以对一打开的文件描述符进行各种控制操作。

      格式:#include<fcntl.h>

                 int fcntl( int fd, int cmd, int arg );

     参数:fd同上,通过cmd的去之决定是否需要arg,此时cmd的取值如下:

F_DUPFD    复制文件描述符fd,返回大于或者等于arg的最低序号的文件描述符,新文件描述符作为函数返回值返回。

F_GETFD    获取close-on-exec标志。如果最后一位是0,则该标志未设置,返回0或者1.

F_SETFD    设置close-on-exec的值为arg。

F_GETFL    对应于fd的文件状态标志作为函数值返回。文件状态标志在open函数已经说明。

F_SETFL    将文件状态标志设置为第三个参数的值。可以更改的标志是O_APPENDO_NONBLOCKO_NDELAY

F_GETOWN   取当前接收SIGIO和SIGURG信号的进程ID或进程租ID。

F_SETOWN   设置接收SIGIO和SIGURG信号的进程ID或进程租ID。正的arg参数表示一个进程ID,负的arg参数表示等于arg的绝对值的进程租ID。

      返回值:失败时返回-1


#include<sys/stat.h>
#include<utime.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdio.h>

#define BLOCK 0
#define BUFSIZE 1024
char *values[]={"123\n","456\n","007\n","421\n","F"};//权限值

int main(int argc,char *argv[])
{
    int fd,flags;
    int i;
    char userno[BUFSIZE],**ptr;
    ptr=values;

    for(i=0;i<BUFSIZE;i++)
    {
        userno[i]='\0';
    }

    setbuf(stdout,(char *)NULL);//清空

    if((fd=open("/dev/tty",O_NDELAY|O_RDONLY))==-1)//打开终端从中读取数据
    {
        printf("open error\n");
        return 1;
    }

    printf("Enter Your user ID:\n");
    sleep(4);

    if(read(fd,userno,BUFSIZE)==-1)
    {
        printf("Bye Bye\n");
        return 2;
    }

    while(strcmp(*ptr,userno,3)!=0&&(strcmp(*ptr,"F")!=0))//判断是否匹配
        ++ptr;

    if(strcmp(*ptr,"F")==0)
    {
        printf("invalid user ID\n");
        return 3;
    }

    flags=fcntl(fd,F_GETFL);
    flags&=BLOCK;
    flags&=fcntl(fd,F_SETFL,flags);//取消O_NDELAY标志,

    printf("enter data:\n");//未输入就一直等待
    i=read(fd,userno,BUFSIZE);
    printf("\n welcome #");
    write(1,userno,i);
    close(fd);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值