您的位置:首页 > 编程语言

Unix高级编程:获取文件元数据、文件夹操作

2017-01-15 22:49 459 查看
1. 计算机大小端,代码参见 big_little.c

#include <stdio.h>

int main(void) {

    short var_a = 0x0001;

    char *var_c = (char *)&var_a;

    if(*var_c) {

        printf("little ...\n");

    }   

    else

        printf("big ...\n");

    return 0;

}

2. 写一个函数实现strcpy字符串拷贝功能,代码参见 mystrcpy.c
char *t_strcpy(char *dest, const char *src);
返回值为什么是char *,而不是 void? "方便函数嵌套调用"用法2和3
char buf[12], buff[12];
t_strcpy(buf, "tarena"); //可能用法1
strlen(t_strcpy(buf, "tarena")); //可能用法2
t_strcpy(buff, t_strcpy(buf, "tarena")); //可能用法3,嵌套2次拷贝

#include <stdio.h>

#include <string.h> //strlen

//dest:值-结果参数

char *t_strcpy1(char *dest, const char *src) {

    char *p_tmp = dest;

    while(*p_tmp++ = *src++); //linux内核

    return dest;

}

char *t_strcpy2(char *dest, const char *src) {

    char *p_tmp = dest;

    while(*src = '\0') {
*p = *src;
p++, src++;
}
*p = *src; //或 *p = '\0';

    return dest;

}

int main(void) {

    char buf[12] = {0}, buff[12] = {0};

    char *s = "tarena";

    t_strcpy(buf, s); 

    printf("buf content: %s\n", buf);

    int size = strlen(t_strcpy(buf, s));//需要string.h

    printf("strlen(buf) = %d\n", size);

    t_strcpy(buff, t_strcpy(buf, s));

    printf("buff content: %s\n", buff);

    return 0;

}

一、获取文件的源数据

什么是文件元数据?

"文件的元数据"就是文件的属性。

文件有文件的"内容"和文件的"属性"。

[-][rw-][rw-][r--] 1 tarena tarena  489 12月  6 09:49 //mystrcpy.c

[1][234][567][890] (除了文件名以外,都是文件的属性,即文件的元数据)

[1]代表文件的类型:

"-" 普通文件 S_IFREG

"d" 文件夹文件 S_IFDIR

"c" 字符设备文件 S_IFCHR

"b" 块设备文件 S_IFBLK

"s" 通讯文件 S_IFSOCK

"l" 软链接文件 S_IFLNK

"p" 管道文件 S_IFIFO "?"

tarena(1) 属主,每个用户都有自己的身份证号,叫"uid"

属主的信息存放在" /etc/passwd/ "文件中

cat /etc/passwd

root:x:0:0:root:/root:/bin/bash //第一行

root 用户名

x 有密码标记,删除就无密码了

0 uid (可记)

0 gid

root 用户的简单备注说明

/root 用户工作的主目录,"~"是其简写

/bin/bash 用户启动的第一个程序bash

tarena(2) 属组,每个属组也有自己的身份证号,叫组id="gid"

属组的信息存放在" /etc/group/ "文件中

cat /etc/group

补充:

1)"stat"也可以查看文件的元数据

"格式:stat 文件名" //查看文件的元数据(属性)

2)链接文件

文件属性中的第一个 1 是硬链接数

每个文件都有且仅有一个自己的"inode"

但是一个inode可以对应多个文件的名字

"硬链接"的inode是同一个,"软链接"不是同一个(软链接也叫符号链接)。

链接的创建和使用

ln hello h //建立hello和h的硬链接,使用 stat hello 和 stat h查看

ln -s hello fileA //建立hello和fileA的软链接"fileA"->"hello"

通过系统调用获取文件的属性

"stat"(2)

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

int stat(const char *path, struct stat *buf);

功能:获取文件的属性

参数:

"path" 文件路径,要获取属性的文件地址

"buf" 将文件的属性填充到buf指定的空间里

补充:

struct stat /*存放文件属性的结构体*/

struct stat {

   dev_t     st_dev;     /* 用于设备文件描述符 */ignore

   ino_t     st_ino;     /* inode号 */ 1

   mode_t    st_mode;    /* 类型/权限protection */ 1

   nlink_t   st_nlink;   /* 硬链接数 */ 1

   uid_t     st_uid;     /* 属主user ID */ 1

   gid_t     st_gid;     /* 属组组ID */ 1

   dev_t     st_rdev;    /* 设备文件ID */ignore

   off_t     st_size;    /* 总字节长度 */ 1

   blksize_t st_blksize; /* blocksize for file system I/O */ignore

   blkcnt_t  st_blocks;  /* number of 512B blocks allocated*/ignore

   time_t    st_atime;   /* 最后一次访问时间 */ 1

   time_t    st_mtime;   /* 最后修改时间 */ 1

   time_t    st_ctime;   /* 状态改变时间 */ 1

};

返回值:

成功 - 返回 0 

失败 - 返回 -1,errno被设置

/*举例验证,文件元数据的获取,代码参见 stat.c*/

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <pwd.h>

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

    struct stat buf;

    int r = stat(argv[1], &buf); //获取文件的属性

    if(r == -1) { //stat函数调用失败

        perror("stat");

        return 1;

    }

    printf("stat success...\n");

    printf("inode number: %lu\n", buf.st_ino);

    printf("hard links: %d\n", buf.st_nlink);

    printf("total size: %ld\n", buf.st_size);

    printf("uid: %d\n", buf.st_uid);

    struct passwd *pass = getpwuid(buf.st_uid);

    if(pass == NULL) {

        printf("not found...\n");

        return 2;

    }

    printf("username: %s\n", pass->pw_name);

    printf("gid: %d\n", buf.st_gid);

    printf("time: %ld\n", buf.st_atime);

    printf("mode: %#o\n", buf.st_mode);

    if(S_ISREG(buf.st_mode)) {

        printf("-");

    }

    else if(S_ISDIR(buf.st_mode)) {

        printf("d");

    }

    printf("######################\n");

    switch(buf.st_mode & S_IFMT) { //做与操作

        case S_IFREG:

            printf("-");

            break;

        case S_IFDIR:

            printf("d");

            break;

        default:

            break;

    }

    printf("\n");

    if(buf.st_mode & S_IRUSR) {

        printf("r");

    } else

        printf("-");

    if(buf.st_mode & S_IWUSR) {

        printf("w");

    } else

        printf("-");

    if(buf.st_mode & S_IXUSR) {

        printf("x");

    } else

        printf("-");

    if(buf.st_mode & S_IRGRP) {

        printf("r");

    } else

        printf("-");

    if(buf.st_mode & S_IWGRP) {

        printf("w");

    } else

        printf("-");

    if(buf.st_mode & S_IXGRP) {

        printf("x");

    } else

        printf("-");

    if(buf.st_mode & S_IROTH) {

        printf("r");

    } else

        printf("-");

    if(buf.st_mode & S_IWOTH) {

        printf("w");

    } else

        printf("-");

    if(buf.st_mode & S_IXOTH) {

        printf("x");

    } else

        printf("-");

    printf("\n");

    return 0;

}

补充:

通过getpwnam(3)获取uid的名字

#include <sys/types.h>

#include <pwd.h>

struct passwd *getpwuid(uid_t uid);

功能:获取uid相关信息

参数:"uid" 指定的uid

返回值:

成功 - 返回一个指向 struct passwd结构体类型的变量地址

失败 - 返回 NULL,没找到或有错误产生,如果是错误,errno被设置

struct passwd {

   char   *pw_name;       /* username */

   char   *pw_passwd;     /* user password */

   uid_t   pw_uid;        /* user ID */

   gid_t   pw_gid;        /* group ID */

   char   *pw_gecos;      /* user information */

   char   *pw_dir;        /* home directory */

   char   *pw_shell;      /* shell program */

};

通过getgrnam(3)获取gid的名字

#include <sys/types.h>

#include <grp.h>

struct group *getgrgid(gid_t gid);

功能:获取gid相关信息

参数:"gid"指定的gid

返回值:

成功 - 返回一个指向 struct group结构体类型的变量地址

失败 - 返回 NULL,没找到或有错误产生,如果是错误,errno被设置

struct group {

   char   *gr_name;       /* group name */

   char   *gr_passwd;     /* group password */

   gid_t   gr_gid;        /* group ID */

   char  **gr_mem;        /* group members */

};

使用ctime(3)将时间由数字转换为字符串类型时间显示

#include <time.h>

char *ctime(const time_t *timep);

功能:转换为日期和时间

参数:"timep" 指定的st_atime

返回值:

成功 - 返回时间值的描述

失败 - 返回 -1,errno被设置

struct tm {

   int tm_sec;         /* seconds */

   int tm_min;         /* minutes */

   int tm_hour;        /* hours */

   int tm_mday;        /* day of the month */

   int tm_mon;         /* month */

   int tm_year;        /* year */

   int tm_wday;        /* day of the week */

   int tm_yday;        /* day in the year */

   int tm_isdst;       /* daylight saving time */

};

二、文件夹的操作

drwxrwxr-x 3 tarena tarena 4096 12月  6 15:55 1206

"r" 读取文件夹的内容

"w" 更新文件夹的内容

"x" 文件夹是否允许你被通过(cd命令的是否成功)

文件夹的内容是文件夹里的文件

程序对文件夹的操作需要使用以下函数:

"opendir"(3)

#include <sys/types.h>

#include <dirent.h>

DIR *opendir(const char *name);

功能:打开一个文件夹

参数:"name" 指定了要打开的文件夹的名字

返回值:

成功 - 一个指向文件夹流的首地址的指针

失败 - 返回 NULL,errno被设置

"readdir"(3)

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

功能:读取一个文件夹

参数:"dirp" opendir(3)的返回值,要读取内容的文件夹

返回值:

成功 - 返回一个结构体指针

失败 - 返回 NULL,到达文件末尾或者错误发生,如果是错误产生,errno被设置

struct dirent {

   ino_t          d_ino;       /* inode号 */

   off_t          d_off;       /* 下一个偏移两 */ ignore

   unsigned short d_reclen;    /* 记录长度 */ ignore

   unsigned char  d_type;      /* 不被所有文件支持 */ ignore

   char           d_name[256]; /* 文件名filename */

};

"closedir"(3)

#include <sys/types.h>

#include <dirent.h>

int closedir(DIR *dirp);

功能:关闭一个文件夹

参数:"dirp" opendir(3)的返回值

返回值:

成功 - 返回 0

失败 - 失败 -1,errno被设置

/*举例验证,代码参见 dir_os.c*/

#include <stdio.h>

#include <sys/types.h>

#include <dirent.h>

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

    DIR *p_dir = opendir(argv[1]);//打开命令行指定的文件夹

    if(!p_dir) {

        perror("opendir");

        return 1;

    }   

    printf("opendir success...\n");

    struct dirent *p_dire; 
//显示文件夹内所有文件inode和文件名

    while((p_dire = readdir(p_dir))) { 
/*if(!p_dire) {
perror("readdir");
return 2;
}*/

        printf("inode: %lu ", p_dire->d_ino);

        printf("filename: %s\n", p_dire->d_name);

    }

    closedir(p_dir);//关闭文件夹

    return 0;

}

"rewinddir"(3)

#include <sys/types.h>

#include <dirent.h>

void rewinddir(DIR *dirp);

功能:重置文件夹流到文件夹的开始位置

参数:"dirp" opendir(3)的返回值

返回值:无返回值。

"telldir"(3)

#include <dirent.h>

long telldir(DIR *dirp);

功能:当前文件夹流的位置

参数:"dirp" opendir(3)的返回值

返回值:

成功 - 返回当前文件夹流的位置

失败 - 返回 -1,errno被设置

/* 举例验证,代码参见 loca_dir.c */

#include <stdio.h>

#include <sys/types.h>

#include <dirent.h>

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

    DIR *p_dir = opendir(argv[1]);//打开命令行指定的文件夹

    if(!p_dir) {

        perror("opendir");

        return 1;

    }   

    printf("opendir success...\n");

    long loc = telldir(p_dir);

    printf("p_dir location: %ld\n", loc);//打印文件夹里内容当前位置

    loc += 1; //当前位置向后移动两个文件

    printf("p_dir location: %ld\n", loc);

    struct dirent *p_dire = readdir(p_dir);

    printf("filename: %s\n", p_dire->d_name);

    rewinddir(p_dir);

    loc = telldir(p_dir);

    printf("p_dir location: %ld\n", loc);

    printf("filename: %s\n", p_dire->d_name);//问题:移动后文件没变?

    closedir(p_dir);//关闭文件夹

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unix 编程
相关文章推荐