AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 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

Existe um *BSD equivalente ao macOS renameatx_np, renomeação de arquivo de troca atômica?

  • 772

Estou procurando criar uma função C compatível com *BSD como a abaixo :

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;
}

No momento, recebo um erro de compilação ( 'renameatx_np' is invalid in C99 [-Wimplicit-function-declaration]) porque, pelo que sei, a renameatx_npfunção é exclusiva do MacOS. Existe uma versão equivalente para *BSD (estou usando o OpenBSD 7.3 atm)?

Que riscos eu estaria correndo se eu removesse o RENAME_SWAPsinalizador e mudasse a função para renameat( edit: eu tentei isso, ele constrói e compila ok, mas resulta em erros ENOENT durante os testes upstream )?

Meu plano é usar as funções linkat e unlinkat para simular a função de renameatx_np.

De que outra forma eu poderia abordar isso?

rename
  • 1 1 respostas
  • 80 Views

1 respostas

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

    A resposta curta para a pergunta do título é não , tanto quanto eu posso dizer.

    No entanto, existem funções nativas adequadas disponíveis para implementar a função fs_ext__swap. Aqui está como eu fiz isso :

    #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

relate perguntas

  • Como substituir uma string em todos os nomes de pastas e arquivos [duplicado]

  • Como pode truncar um nome de arquivo após um determinado caractere

  • Remova caracteres de nomes de arquivos recursivamente

  • Krename: como reiniciar a numeração para cada pasta?

  • Renomeie (acrescentar) arquivos CSV em massa com base em um valor dentro

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

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

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve