【问题标题】:Transfer files in C在 C 中传输文件
【发布时间】:2010-06-24 10:41:11
【问题描述】:

如何将文件从一个文件夹传输到另一个文件夹,其中两个文件夹都存在于 oracle 主目录中?

int main(int argc, char *argv[]){
    char *home, *tmp2;
    home = getenv("ORACLE_HOME");
    temp2 = getenv("ORACLE_HOME");
    strcat (home,"A");
    strcat (tmp2,"B");

//transfer files from home to tmp2

}

strcat 似乎不起作用。在这里,我看到 tmp2 指针没有正确更新。

编辑:操作系统是基于 UNIX 的机器。代码已编辑。 我需要一个执行此复制的二进制文件,目的是无法查看真实代码。因此,我没有考虑使用 shell 脚本作为选项。 A中的文件被加密,然后复制到B,在B中解密并运行。由于文件在 perl 中,我打算使用系统命令在相同的 C 代码中运行它们。

【问题讨论】:

  • 你能把代码放上去吗?当我们甚至看不到 strcat 时,很难看到它。顺便说一句,你是否像这样逃避 \ 字符 \\
  • 看起来像是一次性任务。那么你应该使用 shell 脚本,而不是 C。
  • 为什么会有 strcat 评论?直到那时,我以为我明白了。但这让我很失望,现在我不知道你的问题是什么意思。
  • unix下使用(ba)sh(cp命令)或cmd(xcopy命令)(windows下)
  • “我需要一个二进制文件来执行此复制,目的是无法查看真实代码。”见Kerckhoffs' law。将您的代码保密并不意味着您的加密系统更安全。无论如何,我希望你这样做只是出于教育原因。

标签: c file environment-variables


【解决方案1】:

使用system(3) 命令可能是一个好主意,因为您可以方便地使用 shell 解释器来扩展文件名(通过*),但避免了计算打印命令所需的确切缓冲区长度的麻烦。一个固定长度的缓冲区并确保它不会溢出:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFSZ 0xFFF
int main(void)
{
    char * ohome = getenv("ORACLE_HOME"), cmd[BUFSZ];
    char * fmt="/bin/mv %s/%s/* %s/%s";
    int written = snprintf(cmd, BUFSZ, fmt, ohome, "A", ohome, "B"), ret;
    if ((written < 0) || (written >= (BUFSZ-1))) {
      /* ERROR: print error or ORACLE_HOME env var too long for BUFSZ. */
    }
    if ((ret = system(cmd)) == 0) {
      /* OK, move succeeded. */
    }
    return 0;
}

正如评论者 Paul Kuliniewicz 指出的那样,如果您的 ORACLE_HOME 包含空格或其他特殊字符,这些字符可能会被“system”命令中的子 shell 解释,则可能会出现意外结果。使用execlexecv 系列之一可以让您构建参数,而不必担心shell 解释器会进行自己的解释,但会以使用通配符为代价。

【讨论】:

  • 如果 $ORACLE_HOME 包含空格或任何特殊字符,那么该代码会做出令人惊讶的事情。使用 fork 和 execlp 完全跳过 shell 并确保参数列表以您想要的方式解析会更安全。
  • @Paul: 是的,我首先考虑了这个选项,但是在子shell 中使用通配符来全局化源目录中的所有文件名对我来说似乎是一个巨大的胜利;还分别构建参数值,然后参数更乏味,并且对 OP 没有说明性。
【解决方案2】:

首先,如前所述,您的这种“安全性”完全没有用。拦截正在复制的文件很简单(有很多工具可以监视文件系统更改等),但这是另一回事。

对于第一部分,您可以这样做。要进行实际复制,您必须使用 system() 或读取整个文件然后重新写入,这对于这种快速复制来说有点长。

int main(int argc, char *argv[]){
  char *home, *tmp2;
  home = strdup(getenv("ORACLE_HOME"));
  tmp2 = strdup(getenv("ORACLE_HOME"));
  home = realloc(home, strlen(home)+strlen("A")+1);
  tmp2 = realloc(tmp2, strlen(tmp2)+strlen("B")+1);
  strcat (home,"A");
  strcat (tmp2,"B");
}

顺便说一句,如果你能忍受只是移动文件,那会容易得多,你可以这样做:

rename(home,tmp2);

【讨论】:

    【解决方案3】:

    与您的要求无关,而是对您的代码的评论:

    您可能无法将strcat 指向getenv 的结果,因为getenv 可能(在某些环境中)返回一个指向只读内存的指针。相反,创建一个新缓冲区并将 getenv 的结果 strcpy 放入其中,然后将文件名的其余部分 strcat 放入其中。

    【讨论】:

    • 不管是不是只读的,都是在写入别人的内存,可能是缓冲区溢出。
    【解决方案4】:

    进行传输的快捷方式是使用cp shell 命令进行复制,但使用system 命令而不是使用shell 脚本调用它。

    或者,让您的 C 程序创建一个 shell 脚本来进行复制,运行 shell 脚本,然后将其删除。

    【讨论】: