2013-07-16 7 views
12

私はPOSIXシステムでは、ファイルを削除するunlink()のようなC関数呼び出し、ファイルへのハードリンクを作成するにはlink()、シンボリックファイルを作成するにはsymlink()、ファイルを移動するにはrename()を探していますが、ファイルcopy()の関数ですか?ファイルをコピーするPOSIX関数はありますか?

通常の方法は、ソースファイルを開いてその内容を読み込み、コピー先ファイルを開いてそこにダンプすることです。しかし、なぜ私は前のものすべてを与えられたそのような効用関数を見つけることができないのですか?

+0

ファイルのコピーはかなり時間がかかり、複雑な操作です。 OSが(Windowsのような)システムライブラリの 'CopyFile'機能を持っている場合でも、これは_システムコールとして実装されるのではなく、ユーティリティ機能として実装されます。コピーを作成するにはいくつかの方法がありますが、UN * Xはこれを決してあまり明白にしていません。つまり、ファイルコピーを作成するためのゴールデンパスとして 'copy() 'を販売します。 –

答えて

14

「ファイルをコピー」の話、2つのセマンティクスが存在します

  1. ディープコピー - ファイルに関連付けられているすべてのデータ/メタデータのコピーを含む新しいファイルを作成、しかし、ファイルシステムを構造はこの
  2. シャローコピー - 新しいディレクトリエントリの作成/ファイルソースファイルとして(メタデータの一部またはすべてを、可能な)同じデータを参照

Windows/DOSファイルシステムは伝統的に「浅いコピー」メカニズムを持っていませんでしたが、UN * Xは常にというハードリンクという形で持っていました。

したがって、POSIX/UN * Xはlink(2)システムコールを持ちます。新しい名前で既存の「ファイルデータ」への新しい参照を確立します。つまり、シャローコピーを実行します。

「ディープコピー」システムコールは、たとえば、ファイルレベルのクローン作成を行うために下敷きファイルシステムが重複除外のようなものを実装している場合など、「高速ディープコピー」メカニズムがある場合にのみ意味があります。

そうしないと、そのような関数はライブラリの実装を「劣化」(フォールバック)する必要があります。

「* I/O拡張性のキッチンシンク」であるioctl()であるため、ファイルシステム固有の何かを可能にするUN * Xのメカニズム。可能であれば、この機能を使用してファイルをコピーする方法の例については、BTRFSでファイル複製を使用するための拡張要求でthis GNU coreutils postを参照してください。

WindowsのCopyFileが実際にコールバックなしCopyFileExであることを考えると、私は強くそれは本当にシステムコールだ疑い。これはユーティリティ関数です。 Wine Windows Emulatorについては、kernel32.dllのソース実装を確認して、WineソースのCopyFileExを見つけて、の例を確認してください。となります。
解体/逆コンパイル、Windowsの実際のkernel.dllは、Microsoftのライセンスの下で許可されていないので、私は合法的にWindows自体が同じでないと主張することはできません、すなわちCopyFileはユーザランドの実装、ないシステムコールです。

ここでWindowsとUN * Xを比較すると... NOT すべて UN * X libcはシステムコールです。そのため、UN * Xのマンページでセクション2(sys呼び出し)とセクション3(ランタイムライブラリインタフェース)。 Windows上のkernel.dllの機能についても同じことが言えます。そのうちのいくつかは「ダイレクトパススルー」で、もう1つは単一のシステムコールによって実装されていないより複雑な「ユーティリティ機能」です。

+0

解体物全体について、一部の(ほとんどの)当局では、そうすることは完全に合法です(明示されていても!)。 EULAsはヨーロッパでは法的意味がありません。 **弁護士:**私は弁護士ではありません、もしあなたがこれをやりたいのであれば、弁護士などを求めるべきです。 –

+0

@TimČas:私はそれについては何の主張もしていません - マイクロソフトが提供する非オープンソースバイナリの分解を引用すると、これはまったく同じです。 –

1

同じ方法でファイルを必要としないため、ファイルをコピーするためのユーティリティー機能は見つかりません。それは 'スペアパーツ'から構築することができます。 unlink()symlink()のような関数は、他の関数の点では構築できませんが、仮説のあるcopy_file()などの関数はそうすることができます。

void fcopy(FILE *f1, FILE *f2) 
{ 
    char   buffer[BUFSIZ]; 
    size_t   n; 

    while ((n = fread(buffer, sizeof(char), sizeof(buffer), f1)) > 0) 
    { 
     if (fwrite(buffer, sizeof(char), n, f2) != n) 
      err_syserr("write failed\n"); 
    } 
} 

err_syserr()関数は、引数として渡された文字列とにより暗示エラーメッセージを含むエラー報告のためである:あなたが使用することができ、読み書き用f2ためf1を2つの開いているファイル・ストリームを考えると

errno*;それは返されません。 BUFSIZ<stdio.h>で定義されていますが、より大きな値を使用することもできます。そのようなレポートをエラーにしたくないかもしれませんが、関数が成功すれば0を、失敗した場合は-1を返すことを望みます。

int fcopy(FILE *f1, FILE *f2) 
{ 
    char   buffer[BUFSIZ]; 
    size_t   n; 

    while ((n = fread(buffer, sizeof(char), sizeof(buffer), f1)) > 0) 
    { 
     if (fwrite(buffer, sizeof(char), n, f2) != n) 
      return -1; 
    } 
    return 0; 
} 

この関数はファイルを開かないため、ファイルを閉じることもないので注意してください。つまり、複数の入力ファイルを1つの出力ファイルに連結するために使用することができます。ラッパー関数を使用して、ファイルを読み取り用に、別のファイルを書き込み用に開くことができます。

*実は、err_syserr()は、書式文字列と他の引数を取り、次に説明して終了などのエラーメッセージを報告printf()のような機能があります。

+1

スペアパーツから1つを構築することはできますが、コピーバージョンではファイル属性はコピーされません。セキュリティに関連する新しいファイル属性拡張は、macosxのようなプラットフォーム上のリソースフォークも同様に失われますので、実際に移植可能なコードを書くことはできません...私は知らない、POSIXがボールをここに落としたようです。 。 –

+0

'system(" cp --preserve = all file1 file2 ")' – jxh

+0

私が示しているコードはファイルを開きません。ファイルのオープンや作成コードは属性などを扱う場所です。リソースフォークは本質的に移植性がありません。 POSIXは、何も知らないものの振る舞いを立法するものではありません。特定のプラットフォームを見て、必要なことをするプラットフォーム固有の代替案を見つけることはできますが、移植性はありません。また、APIを設計するのは難しい可能性がある多くの行動があります。修正時間はコピーされますか?パーミッション?ターゲットファイルがすでに存在する場合はどうなりますか?シンボリックリンクですか? ACLセキュリティ情報?その他 –

1

POSIXシステムでは、Win32でCopyFile関数のようなシステムコールを提供しないので、Copy_file()関数を検索する時間を無駄にしないでください。ホイールを再発明したくない場合は、fork()を使用して新しいプロセスを作成し、execl()と呼ぶことをお勧めします。このように:

execl("/bin/cp", "-p", src_file, des_file, (char *)0); 
13

私は、Linux上のcpコマンドでstraceのを実行しようと、それは実際に両方のファイルを開いて、それが一つのファイルからの読み込み、32768バイトのブロック内の他の1に書き込む:

... 
stat64("log", {st_mode=S_IFREG|0644, st_size=352, ...}) = 0 
stat64("copied", 0xbf99e1c0)    = -1 ENOENT (No such file or directory) 
open("log", O_RDONLY|O_LARGEFILE) = 3 
fstat64(3, {st_mode=S_IFREG|0644, st_size=352, ...}) = 0 
open("copied", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, 0644) = 4 
fstat64(4, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0 
read(3, "2012-04-27 22:26:55-0400 [-] Log"..., 32768) = 352 
write(4, "2012-04-27 22:26:55-0400 [-] Log"..., 352) = 352 
read(3, "", 32768)      = 0 
close(4)        = 0 
close(3)        = 0 
... 

はい、そこにはcpシステムコールはありません。それがあなたを助けることを願ってください。

関連する問題