AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 745472
Accepted
Lee
Lee
Asked: 2023-05-10 17:34:39 +0800 CST2023-05-10 17:34:39 +0800 CST 2023-05-10 17:34:39 +0800 CST

是否有 *BSD 等效于 MacOS renameatx_np,原子交换文件重命名?

  • 772

我希望创建一个 *BSD 兼容的 C 函数,如下所示:

int
fs_ext__swap (const char *from, const char *to) {
  int res = renameatx_np(AT_FDCWD, from, AT_FDCWD, to, RENAME_SWAP);

  return res == -1 ? uv_translate_sys_error(errno) : res;
}

目前我收到构建错误 ( 'renameatx_np' is invalid in C99 [-Wimplicit-function-declaration]),因为据我所知,该renameatx_np功能是 MacOS 独有的。*BSD 是否有等效版本(我使用的是 OpenBSD 7.3 atm)?

RENAME_SWAP如果我删除标志并将函数更改为renameat(编辑:我试过这个,它构建和编译正常但在上游测试期间导致 ENOENT 错误),我会冒什么风险?

我的计划是使用linkat和unlinkat函数来模拟renameatx_np的功能。

我还能如何处理这个问题?

rename
  • 1 1 个回答
  • 80 Views

1 个回答

  • Voted
  1. Best Answer
    Lee
    2023-05-15T22:32:16+08:002023-05-15T22:32:16+08:00

    据我所知,对标题问题的简短回答是否定的。

    但是,有足够的本机函数可用于实现 fs_ext__swap 函数。这是我的做法:

    #include <fcntl.h>
    #include <stdint.h>
    #include <uv.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <libgen.h>
    
    #include "../include/fs-ext.h"
    #include "platform.h"
    
    void random_string_len10(char *str){
      // Creates a 10 char long random alpha-numeric string (with in the input char array). Note the input array *str must have length of 11 to allow for 10 chars and a '\0' termination.
      const char charset[] = "0123456789abcdefghijklmnopqrstuvwxyz";
      size_t charset_length = strlen(charset);
      size_t str_length = 10;
    
      for (size_t i = 0; i < str_length; ++i){
        str[i] = charset[arc4random_uniform(charset_length -1)];
      }
      str[str_length] = '\0';
    }
    
    int append_file_to_path_string(char *path, char *filename, char *result)
    {
      // function to append a filename to directory name. Directory name must have a slash at the end.
      size_t path_length = strlen(path);
      size_t filename_length = strlen(filename);
      size_t result_size = path_length + filename_length + 1; // +1 for null terminator
    
      if (result_size > PATH_MAX ) {
          fprintf(stderr, "Cannot append file name to to path; result size is too large!\n");
          return EXIT_FAILURE;
      }
    
      strncpy(result, path, path_length);
      strncpy(result + path_length, filename, filename_length);
      result[result_size - 1] = '\0'; // Ensure null termination
    
      return EXIT_SUCCESS;
    }
    
    void append_slash(char *str) {
      // appends a slash to an input string
        size_t len = strlen(str);
        if (len > 0 && str[len -1] != '/' && len < PATH_MAX-1) {
            str[len] = '/';
            str[len+1] = '\0';
        }
    }
    
    int
    swap_directories (const char *from, const char *to) {
      // *****************
      // Prep temporary directory with same underlying path as from
      char temp_dir[PATH_MAX];
      snprintf(temp_dir,sizeof(temp_dir), "%s.swap_temp", from);
    
      // *****************
      // Perform series of rename operations to swap to and from directories. 
    
      // 1. Rename fromdir to tempdir
      if( renameat( AT_FDCWD, from, AT_FDCWD, temp_dir) == -1) {
        printf("Renameat from - temp failed.\n");
        return uv_translate_sys_error(errno);  
      }  else {
        printf("Renameat from - to  worked!\n");
      }
      // 2. Rename todir to fromdir
      if( renameat( AT_FDCWD, to, AT_FDCWD, from) == -1) {
        printf("Renameat to - from failed.\n");
        return uv_translate_sys_error(errno);  
      }  else {
        printf("Renameat to - from  worked!\n");
      } 
      // 3. Rename temp_dir(now original fromdir) to todir
      if( renameat( AT_FDCWD, temp_dir, AT_FDCWD, to) == -1) {
        printf("Renameat temp - to failed.\n");
        if( renameat( AT_FDCWD, from, AT_FDCWD, to) == -1) {  printf("Rollback failed.\n");}
        return uv_translate_sys_error(errno);  
      }  else {
        printf("Renameat temp - to  worked!\n");
      }
    
      return 0;
    }
    
    int
    swap_files (const char *from, const char *to) {
    
      // *****************
      // Prep temporary files with random names. Must share path of input files to avoid cross file system error.
    
      char temp_nameA[11];
      char temp_nameB[11];
    
      random_string_len10(temp_nameA);
      random_string_len10(temp_nameB);
    
      char *to_path = dirname(strdup(to));    
      size_t pathlen = strlen(to_path);
    
      if ( pathlen + 1 < PATH_MAX){
          append_slash(to_path);    
      } else {
        return -1;
      }
    
      char temp_fileA[PATH_MAX];
      char temp_fileB[PATH_MAX];
    
      append_file_to_path_string(to_path,temp_nameA,temp_fileA);
      append_file_to_path_string(to_path,temp_nameB,temp_fileB); 
    
      // *****************
      // Perform series of linking and unlinking operations to swap to and from file. "TO-file" and "FROM-file" in the comments denote the original underlying file objects.
    
      // 1. LINK (from,tempA) tempA and from can access FROM-file
      if( linkat( AT_FDCWD, from, AT_FDCWD, temp_fileA,0)== -1) {
        printf("link(from tempA) failed.\n");
        return uv_translate_sys_error(errno); 
    
      }
      else {
        printf("link(from tempA) worked!\n");
      }
      // 2. LINK (to,tempB) tempB and to can access TO-file
      if( linkat( AT_FDCWD, to, AT_FDCWD, temp_fileB,0)== -1) {
        printf("link(to tempB) failed.\n");
        return uv_translate_sys_error(errno);  
      } else {
        printf("link(to tempB) worked!\n");
      }
       // 3. UNLINK (from) only tempA can access FROM-file
      if( unlinkat( AT_FDCWD, from,0)== -1) {
        printf("unlink(from) failed.\n");
        return uv_translate_sys_error(errno); 
      } else {
        printf("unlink(from) worked!\n");
      }
    
      // 4. UNLINK (to) only tempB can access TO-file
      if( unlinkat( AT_FDCWD, to,0)== -1) {
        printf("unlink(to) failed.\n");
        return uv_translate_sys_error(errno); 
      }  else {
        printf("unlink(to) worked!\n");
      }
    
      // 5. LINK (tempA,to) tempA and to can access FROM-file
      if( linkat( AT_FDCWD, temp_fileA, AT_FDCWD, to,0)== -1) {
        printf("link(tempB to) failed.\n");
        return uv_translate_sys_error(errno);  
      }  else {
        printf("link(to tempB) worked!\n");
      }
    
      // 6. LINK (tempB,from) tempB and from can access TO-file
      if( linkat( AT_FDCWD, temp_fileB, AT_FDCWD, from,0)== -1) {
        printf("link(tempB from) failed.\n");
        return uv_translate_sys_error(errno);  
      } else {
        printf("link(tempB,from) worked!\n");
      }
    
      // 7. UNLINK (tempA) only to can access FROM-file
      if( unlinkat( AT_FDCWD, temp_fileA,0)== -1) {
        printf("unlink(tempA) failed.\n");
        return uv_translate_sys_error(errno); 
      } else {
        printf("unlink(tempA) worked!\n");
      }
    
      // 8. UNLINK (tempB) only from can access TO-file
      if( unlinkat( AT_FDCWD, temp_fileB,0)== -1) {
        printf("unlink(tempB) failed.\n");
        return uv_translate_sys_error(errno); 
      } else {
        printf("unlink(tempB) worked!\n");
      }
    
      return 0;
    }
    
    int
    fs_ext__swap (const char *from, const char *to) {
      // use sys/stat.h to determine if from and to are files or directories
      struct stat st_from, st_to;
    
      int from_is_dir = stat(from, &st_from) == 0 && S_ISDIR(st_from.st_mode);
      int to_is_dir = stat(to, &st_to) == 0 && S_ISDIR(st_to.st_mode);
    
      // Call swap_files or swap_directories dependendent whether inputs are files or directories:
      switch (from_is_dir * 2 + to_is_dir) {
        case 0: // Both are files
          if( swap_files(from,to)!=0){ return uv_translate_sys_error(errno);} // swap files
          return 0;
        case 1: // from is file to is dir: file dir-swap seems to work with case 3 code, so no return statements included.
        case 2: // from is dir to is file
        case 3: // Both are dirs
          if (swap_directories(from,to)!=0){  return uv_translate_sys_error(errno);}
          return 0; 
        default: // something else:  ERR
          return -1;
        }
    }
    
    • 0

相关问题

  • 如何替换所有文件夹和文件名中的字符串[重复]

  • 如何在某个字符后截断文件名

  • 递归地从文件名中删除字符

  • Krename:如何为每个文件夹重新编号?

  • 根据其中的值批量重命名(附加)CSV 文件

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve