link, linkat, unlink, unlinkat, and remove Functions

本文深入探讨Linux中文件的链接操作(link和linkat)与删除操作(unlink和unlinkat),包括其作用原理、参数解释及实例演示。重点阐述了如何通过链接创建文件的硬链接与符号链接,以及在不同场景下使用unlink和unlinkat删除文件或目录的详细步骤。

Linux 4.2.0

在之前的章节,我们知道一个文件可以有多个dirctory entries指向它的i-node。我们可以使用link , linkat来创建已经存在文件的链接(link)
原型如下:

#include <unistd.h>

int link(const char *oldpath, const char *newpath);

#include <fcntl.h>           /* Definition of AT_* constants */
#include <unistd.h>

int linkat(int olddirfd, const char *oldpath,
                  int newdirfd, const char *newpath, int flags);
//Return: 0 if OK, -1 on error

link() creates a new link (also known as a hard link) to an existing file.

If newpath exists, it will not be overwritten.

This new name may be used exactly as the old one for any operation;both names refer to the same file (and so have the same permissions and ownership) and it is impossible to tell which name was the “original”.

linkat

Thelinkat() system call operates in exactly the same way as link(), except for the differences described here.:

  1. If the pathname given in oldpath is relative, then it is interpreted relative to the directory referred to by the file descriptor olddirfd (rather than relative to the current working directory of the calling process, as is done by link() for a relative pathname).

  2. If oldpath is relative and olddirfd is the special value AT_FDCWD, then oldpath is interpreted relative to the current working directory of the calling process (like link()).

  3. If oldpath is absolute, then olddirfd is ignored.

  4. The interpretation of newpath is as for oldpath, except that a relative pathname is interpreted relative to the directory referred to by the file descriptor newdirfd.

flags argument

如果flag是AT_SYMLINK_FOLLOW,创建的link是用于symbolic link指向的目标。如果flag被清除,则link用于symblic link本身。

Besides

directory entry的新建和link count的增加必须是原子操作。

大部分实现都需要路径名在同一个文件系统上,尽管POSIX.1允许实现支持link能跨越文件系统。支持创建directorieshard link(硬链接)的实现,都只能让超级用户进行该项操作。这条限制(constraint)是因为hard link可能在文件系统中造成循环(loops),这是文件系统不法处理的。(在4.17节我们会展示symbolic link的loop实例)。因此,许多文件系统不允许(目录)directories的硬链接(hard link)。

原型:

#include <unistd.h>
int unlink(const char *pathname);

#include <fcntl.h>           /* Definition of AT_* constants */
#include <unistd.h>
int unlinkat(int dirfd, const char *pathname, int flags);
//both Return: 0 if OK, -1 on error

这些系统调用会移除目录条目(directory entry)并且减少pathename引用的文件的链接数目link count。如果文件还有其他的链接(link),文件的内容还可以通过其他链接访问。如果产生error,文件不会发生变化。

As mentioned earlier, to unlink a file, we must have write permission and execute permission in the directory containing the directory entry, as it is the directory entry that we will be removing. Also, as mentioned in Section 4.10, if the sticky bit is set in this directory we must have write permission for the directory and meet one of the following criteria:
• Own the file
• Own the directory
• Have superuser privileges

仅仅当link count达到0,文件的内容才会被删除。另一种阻止文件内容被删除的条件就是,一些进程open了该文件,文件的内容也不会被删除。当某文件被关闭了(closed),内核会先确定打开(open)该文件的进程数量,如果为0,此时内核会继续确定link count,如果还为0,文件内容被删除。

unlinat

pathname为相对路径,unlinkat会将其看做fd开的目录的相对路径。
如果fd值为AT_FDCWD时,pathname就是相对路径,相对于调用进程的当前工作目录。如果pathname是绝对路径,fd直接被忽略。

flag

用于改变unlinkat默认行为。
1. AT_REMOVEDIR: 用于删除目录,类似于使用rmdir命令。
2. clear: unlinkat操作和unlink一致。

Example

#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main()
{
    if(open("tempfile", O_RDWR|O_CREAT, S_IRWXO) < 0)
    {
        fprintf(stderr, "open file error %s\n", strerror(errno));
        exit(-1);
    }
    if(unlink("tempfile") < 0)
    {
        fprintf(stderr, "unlink file error %s\n", strerror(errno));
        exit(-1);
    }

    printf("file unlinked\n");
    sleep(15); 
    printf("done\n");

    return 0;
}

sleep(15),用于睡眠15s,定义在unistd中。

This property of unlink is often used by a program to ensure that a temporary file it creates won’t be left around in case the program crashes. The process creates a file using either open or creat and then immediately calls unlink. The file is not deleted, however, because it is still open. Only when the process either closes the file or terminates, which causes the kernel to close all its open files, is the file deleted.

If pathname is a symbolic link, unlink removes the symbolic link, not the file referenced by the link. There is no function to remove the file referenced by a symbolic link given the name of the link.

The superuser can call unlink with pathname specifying a directory if the file system supports it, but the function rmdir should be used instead to unlink a directory. We describe the rmdir function in Section 4.21.

remove

We can also unlink a file or a directory with the remove function. For a file, remove is identical to unlink. For a directory, remove is identical to rmdir.

remove - remove a file or directory

#include <stdio.h>

int remove(const char *pathname);
//Returns: 0 if OK, -1 on error
在 SAP RAP(RESTful ABAP Programming)开发中,实现 LinkUnlink 操作通常涉及对关联实体(navigation properties)的管理。RAP 模型基于 CDS(Core Data Services)视图,并通过服务绑定(service binding)暴露为 OData 服务。LinkUnlink 操作用于建立或解除两个实体之间的关系,例如将一个业务对象关联到另一个业务对象。 ### 实现 Link Action 在 RAP 中,Link 操作通常通过 OData 协议中的 `bind` 操作实现,即在客户端发送一个 POST 请求,将目标实体的 ID 添加到导航属性中。以下是实现 Link 操作的关键步骤: 1. **定义 CDS 视图中的关联关系** 在 CDS view 中定义导航属性,例如: ```sql define view entity I_MyEntity as select from MyTable association [0..1] to I_RelatedEntity as _RelatedEntity on $projection.MyKey = _RelatedEntity.Key { key MyTable.Key, MyTable.Value, _RelatedEntity } ``` 2. **在 Behavior Pool 中实现绑定逻辑** 在 behavior pool 中定义 `on bind` 方法,用于处理 Link 操作的业务逻辑: ```abap method on_bind_related_entity. " 实现绑定逻辑,例如检查权限或执行额外的业务规则 endmethod. ``` 3. **OData 调用示例** 客户端可通过如下 OData 请求建立链接: ```http POST /sap/opu/odata4/some-service/MyEntity(guid'123')/MyNamespace.MyEntity/_RelatedEntity/$ref HTTP/1.1 Content-Type: application/json { "@odata.id": "/sap/opu/odata4/some-service/RelatedEntity(guid'456')" } ``` ### 实现 Unlink Action Unlink 操作通常通过 OData 协议中的 `unbind` 操作实现,即客户端发送一个 DELETE 请求,从导航属性中移除目标实体的引用。 1. **在 Behavior Pool 中实现解绑逻辑** 在 behavior pool 中定义 `on unbind` 方法,用于处理 Unlink 操作: ```abap method on_unbind_related_entity. " 实现解绑逻辑,例如清理关联数据或触发日志记录 endmethod. ``` 2. **OData 调用示例** 客户端可通过如下 OData 请求解除链接: ```http DELETE /sap/opu/odata4/some-service/MyEntity(guid'123')/MyNamespace.MyEntity/_RelatedEntity(guid'456')/$ref HTTP/1.1 ``` ### 注意事项 - **权限控制**:在实现 LinkUnlink 操作时,应考虑权限验证,确保用户具有执行操作的权限。 - **事务一致性**:如果 Link/Unlink 操作涉及多个数据变更,建议使用事务控制(如 `BEGIN OF TRANSACTION`)以确保一致性。 - **日志记录**:建议记录操作日志,以便审计和调试。 - **错误处理**:在 `on bind` 和 `on unbind` 方法中应包含适当的错误处理机制,以应对无效输入或业务规则冲突的情况。 ### 示例代码片段(Behavior Pool) ```abap class ZCL_MY_ENTITY_BEHAVIOR definition. public section. methods: on_bind_related_entity for bind of I_MyEntity\_RelatedEntity, on_unbind_related_entity for unbind of I_MyEntity\_RelatedEntity. endclass. class ZCL_MY_ENTITY_BEHAVIOR implementation. method on_bind_related_entity. " 验证输入 if input is initial. raise exception type /iwbep/cx_mgw_busi_exception exporting textid = 'MY_ENTITY.BIND.NO_INPUT'. endif. " 执行绑定逻辑 " ... endmethod. method on_unbind_related_entity. " 执行解绑逻辑 " ... endmethod. endclass. ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值