特殊文件--符号链接操作

1.创建符号链接

 

#include<unistd.h>
定义函数 int symlink( const char * oldpath,const char * newpath);
函数说明 symlink()以参数newpath指定的名称来建立一个新的连接(符号连接)到参数oldpath所指定的已存在文件。参数oldpath指定的文件不一定要存在 (如果不存在,符号链接也可建立,只是利用该符号链接读或写文件时会出粗),如果参数newpath指定的名称为一已存在的文件则不会建立连接。
返回值 成功则返回0,失败返回-1,错误原因存于errno。
错误代码 EPERM 参数oldpath与newpath所指的文件系统不支持符号连接
EROFS 欲测试写入权限的文件存在于只读文件系统内
EFAULT 参数oldpath或newpath指针超出可存取内存空间。
ENAMETOOLONG 参数oldpath或newpath太长
ENOMEM 核心内存不足
EEXIST 参数newpath所指的文件名已存在。
EMLINK 参数oldpath所指的文件已达到最大连接数目
ELOOP 参数pathname有过多符号连接问题
ENOSPC 文件系统的剩余空间不足
EIO I/O 存取错误

 


2.读写符号链接的目的文件

 

用户可以像操作普通文件一样操作链接文件,这时实际操作的是符号链接所指向的文件。

 

3.读写多重符号链接的目的文件

 

当创建了一个符号连接时,read和write函数会一直跟踪符号链接,知道遇到实际目的文件为止。因此即使存在多重符号链接,也可随便操作该链接链上的任意一个,实现对实际文件的读写。

 

范例:

//mul_link.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#define MAX 1024

int main(void)
{
    int fd;
    char buf[MAX];
    int n;

if(symlink("test.txt", "sl") == -1){ /* 创建一个符号链接,指向test.txt文件 */
        perror("fail to create symbol link");
        exit(1);
    }
   
    /* 再次创建一个符号链接,指向sl。就此形成了一个符号链接链:sl2->sl->test.txt
    * test.txt文件是目的文件,也是该符号链接链的重点
    */
if(symlink("sl", "sl2") == -1){
        perror("fail to create symbol link");
        exit(1);
    }
       
    if((fd = open("sl2", O_RDWR)) == -1){ /* 打开的实际上是目的文件test.txt */
        perror("fail to open");
        exit(1);
    }

    printf("already create symbol-links/n");

    if((n = read(fd, buf, MAX)) == -1){ /* 读文件的内容 */
        perror("fail to read");
        exit(1);
    }
    buf[n] = '/0';

    printf("file content is : %s/n", buf); /* 输出结果*/

    strcat(buf, ", admin");

    if(write(fd, buf, strlen(buf)) == -1){ /* 向该文件写内容 */
        perror("fail to write");
        exit(1);
    }

    printf("done/n"); /* 输出提示信息 */

    close(fd);

    return 0;
}

 

 

4.读写符号链接

符号链接是文件的一种,这种文件也哟自己保存的内容。符号链接中保存的是目的文件的路径,其是一个字符串。

若要读取一个符号链接本身的内容,可用如下 函数:

 

#include<unistd.h>
定义函数 int readlink(const char * path ,char * buf,size_t bufsiz);
函数说明 readlink()会将参数path的符号连接内容存到参数buf所指的内存空间,返回的内容不是以NULL作字符串结尾,但会将字符串的字符数返回。若参数bufsiz小于符号连接的内容长度,过长的内容会被截断。
返回值 执行成功则传符号连接所指的文件路径字符串,失败则返回-1,错误代码存于errno。
错误代码 EACCESS 取文件时被拒绝,权限不够
EINVAL 参数bufsiz 为负数
EIO I/O 存取错误。
ELOOP 欲打开的文件有过多符号连接问题。
ENAMETOOLONG 参数path的路径名称太长
ENOENT 参数path所指定的文件不存在
ENOMEM 核心内存不足
ENOTDIR 参数path路径中的目录存在但却非真正的目录。

 

buf缓冲区中的字符串不以'/0'结束,必要时自己添

 

 

范例:

//readlink.c

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

 

#define MAX 1024

 

int main()

{

char buf[MAX];

int fd;

 

if(syslink("root/alei/linux/code/test.txt","s1")==-1){

perror("fail to create symbol-link");

exit(1);

}

 

if(syslink("s1","s2")==-1){

perror("fail to create symbol-link");

exit(1);

}

 

if(readlink("s1",buf,MAX)==-1){

perror("fail to read link");

exit(1);

}

printf("%s/n",buf);

 

if(readlink("s1",buf,MAX)==-1){

perror("fail to read link");

exit(1);

}

printf("%s/n",buf);

 

return 0;

}

 

如果使用一个不存在的文件作为符号链接的目的文件,readlink函数也可以成功读取符号链接的内容,因为readlink函数在符号链接的数据库爱上读取内容,该内容是一个路径名,只是该路径端点上的文件不存在而已。


5.获得符号链接的状态

符号链接是一种特殊文件,这文件也有自己的状态。

 

//sys_stat.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main(void)
{
    struct stat buf; /* 存储文件状态信息 */
   
    if(stat("sl", &buf) == -1){
        perror("fail to stat");
    exit(1);
}
   
    printf("permission : %d/n", buf.st_mode); /* 打印文件权限字 */
    printf("inode number : %d/n", buf.st_ino); /* 打印i节点号 */
    printf("device number : %d/n", buf.st_dev); /* 打印文件系统设备号 */
    printf("r-device number : %d/n", buf.st_rdev); /* 打印硬件设备设备号 */
    printf("link : %d/n", buf.st_nlink); /* 打印硬链接数 */
    printf("uid : %d/n", buf.st_uid); /* 打印所有者用户ID */
    printf("gid : %d/n", buf.st_gid); /* 打印所有者组ID */
    printf("file size : %d/n", buf.st_size); /* 打印文件的大小 */
    printf("access time : %d/n", buf.st_atime); /* 打印最近一次的访问时间*/
    printf("motify time : %d/n", buf.st_mtime); /* 打印最近一次修改文件内容的时间 */
    printf("change time : %d/n", buf.st_ctime); /* 打印最近一次修改文件属性的时间 */
    printf("buf size : %d/n", buf.st_blksize); /* 打印最适的缓冲区大小 */
    printf("block size : %d/n", buf.st_blocks); /* 打印文件在外存上占用的盘块数 */

    if(stat("test.txt", &buf) == -1){
        perror("fail to stat");
    exit(1);
}

    printf("permission : %d/n", buf.st_mode); /* 打印文件权限字 */
    printf("inode number : %d/n", buf.st_ino); /* 打印i节点号 */
    printf("device number : %d/n", buf.st_dev); /* 打印文件系统设备号 */
    printf("r-device number : %d/n", buf.st_rdev); /* 打印硬件设备设备号 */
    printf("link : %d/n", buf.st_nlink); /* 打印硬链接数 */
    printf("uid : %d/n", buf.st_uid); /* 打印所有者用户ID */
    printf("gid : %d/n", buf.st_gid); /* 打印所有者组ID */
    printf("file size : %d/n", buf.st_size); /* 打印文件的大小 */
    printf("access time : %d/n", buf.st_atime); /* 打印最近一次的访问时间*/
    printf("motify time : %d/n", buf.st_mtime); /* 打印最近一次修改文件内容的时间 */
    printf("change time : %d/n", buf.st_ctime); /* 打印最近一次修改文件属性的时间 */
    printf("buf size : %d/n", buf.st_blksize); /* 打印最适的缓冲区大小 */
    printf("block size : %d/n", buf.st_blocks); /* 打印文件在外存上占用的盘块数 */
   
return 0;
}

 

这两次输出的内容是一样的,因为使用stat函数时,实际得到的是目的文件的状态信息。

 

 

如果要知道符号链接文件本身的文件状态信息。可用:

 

#include<sys/stat.h>
#include<unistd.h>
定义函数 int lstat (const char * file_name.struct stat * buf);
函数说明 lstat()与stat()作用完全相同,都是取得参数file_name所指的文件状态,其差别在于,当文件为符号连接时,lstat()会返回该link本身的状态。详细内容请参考stat()。
返回值 执行成功则返回0,失败返回-1,错误代码存于errno。

 

范例:

//sym_lstat.c

 

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main(void)
{
    struct stat buf; /* 存储文件状态信息 */
   
    if(lstat("sl", &buf) == -1){
        perror("fail to stat");
    exit(1);
}
   
    printf("permission : %d/n", buf.st_mode); /* 打印文件权限字 */
    printf("inode number : %d/n", buf.st_ino); /* 打印i节点号 */
    printf("device number : %d/n", buf.st_dev); /* 打印文件系统设备号 */
    printf("r-device number : %d/n", buf.st_rdev); /* 打印硬件设备设备号 */
    printf("link : %d/n", buf.st_nlink); /* 打印硬链接数 */
    printf("uid : %d/n", buf.st_uid); /* 打印所有者用户ID */
    printf("gid : %d/n", buf.st_gid); /* 打印所有者组ID */
    printf("file size : %d/n", buf.st_size); /* 打印文件的大小 */
    printf("access time : %d/n", buf.st_atime); /* 打印最近一次的访问时间*/
    printf("motify time : %d/n", buf.st_mtime); /* 打印最近一次修改文件内容的时间 */
    printf("change time : %d/n", buf.st_ctime); /* 打印最近一次修改文件属性的时间 */
    printf("buf size : %d/n", buf.st_blksize); /* 打印最适的缓冲区大小 */
    printf("block size : %d/n", buf.st_blocks); /* 打印文件在外存上占用的盘块数 */

    if(stat("test.txt", &buf) == -1){
        perror("fail to stat");
    exit(1);
}

    printf("permission : %d/n", buf.st_mode); /* 打印文件权限字 */
    printf("inode number : %d/n", buf.st_ino); /* 打印i节点号 */
    printf("device number : %d/n", buf.st_dev); /* 打印文件系统设备号 */
    printf("r-device number : %d/n", buf.st_rdev); /* 打印硬件设备设备号 */
    printf("link : %d/n", buf.st_nlink); /* 打印硬链接数 */
    printf("uid : %d/n", buf.st_uid); /* 打印所有者用户ID */
    printf("gid : %d/n", buf.st_gid); /* 打印所有者组ID */
    printf("file size : %d/n", buf.st_size); /* 打印文件的大小 */
    printf("access time : %d/n", buf.st_atime); /* 打印最近一次的访问时间*/
    printf("motify time : %d/n", buf.st_mtime); /* 打印最近一次修改文件内容的时间 */
    printf("change time : %d/n", buf.st_ctime); /* 打印最近一次修改文件属性的时间 */
    printf("buf size : %d/n", buf.st_blksize); /* 打印最适的缓冲区大小 */
    printf("block size : %d/n", buf.st_blocks); /* 打印文件在外存上占用的盘块数 */
   
return 0;
}
这一次输出的内容是不一样的。

 

6.更改符号链接的所有者

chown函数用于符号链接时,会改变符号链接所指向的文件的所有者的用户ID,而不是链接文件本身的用户ID。

 

若要改变符号链接本身的所有者ID,用如下函数:

 

#include <unistd.h>

int lchown(const char * pathname,uid_t owner,gid_t group);

 

owner的值为-1时,符号链接的所有者ID不发生变化,同理对于组ID也是一样的。

 

//sym_chown.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>

int main(void)
{
    struct stat statbuf;
    char buf[1024];
   
    printf("before changing/n/n"); /* 输出提示信息 */

    if(stat("test.txt", &statbuf) == -1){ /* 得到目的文件的状态信息 */
        perror("fail to get status");
        exit(1);   
    }
   
    printf("the owner of test.txt is : %d/n", (unsigned int)statbuf.st_uid);
    printf("the group of test.txt is : %d/n", (unsigned int)statbuf.st_gid);

    if(lstat("sl", &statbuf) == -1){ /* 使用lstat函数得到符号链接的状态信息 */
        perror("fail to get status");
        exit(1);   
    }
   
    printf("the owner of sl is : %d/n", (unsigned int)statbuf.st_uid);
    printf("the group of sl is : %d/n", (unsigned int)statbuf.st_gid);
   
    if(chown("sl", 0, -1) == -1){ /* 改变目的文件的所有者 */
        perror("fail to change owner");
        exit(1);   
    }
   
    printf("after changing/n"); /* 输出提示信息 */

    if(stat("test.txt", &statbuf) == -1){ /* 再次得到目的文件的文件状态信息 */
        perror("fail to get status");
        exit(1);   
    }
   
    printf("the owner of test.txt is : %d/n", (unsigned int)statbuf.st_uid);
    printf("the group of test.txt is : %d/n", (unsigned int)statbuf.st_gid);

    if(lstat("sl", &statbuf) == -1){ /* 使用lstat函数得到符号链接本身的文件状态信息 */
        perror("fail to get status");
        exit(1);   
    }
   
    printf("the owner of sl is : %d/n", (unsigned int)statbuf.st_uid);
    printf("the group of sl is : %d/n", (unsigned int)statbuf.st_gid);
   
    return 0;   
}

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值