0

私はこれに夢中になります。ファイルを保存および抽出できるアーカイブ ライブラリを作成しようとしています。アーカイブ ファイルは次のようになります。

<0,/home/user/file.txt,154,0755>
file contents (154 byte)

各ファイルは、ヘッダー ( <...> )、4 つの「タグ」 (コンマで区切られている)、ファイルの種類 (ファイルの場合は 0、ディレクトリの場合は 1)、パス、バイト単位のサイズ、アクセス許可 (8 進数) で識別されます。stat システム コールを使用してサイズとアクセス許可を取得します (Linux を使用しています)。私の問題は、8 進数値を st_mode から文字列に変換し、それをアーカイブ ファイル (ヘッダーの 4 番目のタグ) に保存してから、抽出して chmod syscall で使用する必要があることです。

それを文字列に変換するには、次を使用します。

char mode[6];
sprintf (mode, "%o", statr.st_mode);

それを取得するには、atoiを使用しますが、機能しないようです。たとえば、4 番目のタグに格納されている値は 100644 ですが、chmod はパーミッションを間違って設定しています (ユーザーがファイルを読み取ることができません)。

よく説明したかどうかわかりませんが、必要に応じてコード全体を投稿します(ただし、実装の問題はないと思います。8進数から文字列への変換の間の問題にすぎません)

編集:解決しました!実際には strtol メソッドは機能しましたが、それをディレクトリにも適用するのを忘れていました (そのため、ファイルを含むディレクトリを抽出すると、フォルダーのパーミッション マスクが原因で Segfault が発生しました)。みんな助けてくれてありがとう!

4

3 に答える 3

1

私の知る限り、これを行うための UNIX 標準関数はありません。

ほとんどのst_mode場合、必要な各アクセス許可ビットを取得し、意味のあるものに変換するには、マスクする必要があります。

関連記事

これを行うにはもっと簡単な方法があるかもしれませんが、興味のある各ビットを取得する方法を示す簡単な例を含めました。これはコンパイルされ、期待どおりに実行されたようです。

st_mode.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


#define SET_UID_BIT     0x4000
#define SET_GID_BIT     0x2000
#define STICKY_BIT      0x1000

// Readable USER bits defined here
#define USR_READ_BIT    0x400
#define USR_WRITE_BIT   0x200
#define USR_EXEC_BIT    0x100

// Readable GROUP bits defined here
#define GRP_READ_BIT    0x040
#define GRP_WRITE_BIT   0x020
#define GRP_EXEC_BIT    0x010

// Readable OTHER bits defined here
#define OTH_READ_BIT    0x004
#define OTH_WRITE_BIT   0x002
#define OTH_EXEC_BIT    0x001


int main()
{
    // The file I'm opening
    const char fp[] = "myfile.txt"; // -rw-rw-r--
    struct stat stats;

    // Get the stats
    if ( 0 == stat( fp, &stats ) )
    {
        // store st_mode
        mode_t mode = stats.st_mode;
        // init printable_mode
        unsigned int printable_mode = 0;        


        // Test for each permission bit in mode.
        // If the bit is present, mark the corresponding bit in printable_mode
        // using defined bits above.
        if( mode & S_ISUID )
        printable_mode |= SET_UID_BIT;

        if( mode & S_ISGID )
        printable_mode |= SET_GID_BIT;

        if( mode & S_ISVTX )
        printable_mode |= STICKY_BIT;

        if( mode & S_IRUSR )
        printable_mode |= USR_READ_BIT;

        if( mode & S_IWUSR )
        printable_mode |= USR_WRITE_BIT;

        if( mode & S_IXUSR )
        printable_mode |= USR_EXEC_BIT;

        if( mode & S_IRGRP )
        printable_mode |= GRP_READ_BIT;

        if( mode & S_IWGRP )
        printable_mode |= GRP_WRITE_BIT;

        if( mode & S_IXGRP )
        printable_mode |= GRP_EXEC_BIT;

        if( mode & S_IROTH )
        printable_mode |= OTH_READ_BIT;

        if( mode & S_IWOTH )
        printable_mode |= OTH_WRITE_BIT;

        if( mode & S_IXOTH )
        printable_mode |= OTH_EXEC_BIT;

        // Let's see what it looks like....
        printf("%04x\n", printable_mode);
        printf("%x\n", mode);
    }

    return 0;
}
于 2012-07-26T14:10:16.427 に答える
0

データを先頭に 8 進数で書き込む場合は、次のよう0に読み取ることができますstrtol

char mode[8];
snprintf(mode, 8, "0%o", statr.st_mode);
strtol(mode, NULL, 0);

strtolまたは、引数8として指定して読み取ることもできますbase。この場合、先頭0は不要です。

char mode[7];
snprintf(mode, 8, "%o", statr.st_mode);
strtol(mode, NULL, 8);
于 2012-07-26T14:23:13.393 に答える
0

ストラトゥールを使用します。たとえば、次のテスト プログラムは "100644" (8 進数) を正しく解釈します。変換後、変換されていない*endptr最初の文字を指します。の場合、文字列全体が消費されています。それ以外の場合は、エラーが発生しています (たとえば、"1234X" で strtoul を呼び出すと、'X' で停止します)。8 進数の 10644 は 33188 (10 進数) に等しいことに注意してください。*endptr == 0

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

int main() {

   char *s = "100644";
   char *endptr;

   unsigned long result = strtoul(s, &endptr, 8);

   if (*endptr)
      printf("conversion error!\n");

   printf("result: %lu == octal %lo\n", result, result);

   return 0;
}
于 2012-07-26T14:24:20.393 に答える