53375


次のプログラムを x86_64 Linux 環境 (Centos7) でコンパイルし、CIFSでマウントした ディレクトリの中身を 表示させようとしました。

gcc のオプションに `-m32` をつけて 32bit でコンパイルしたときと、64bit でコンパイルした場合で、動作が異なり 32bit だと正しく
表示されません。

なぜ 32bit 版は正常に動作しないのでしょうか。  
または、正常に動作させる方法が分かれば教えてください。

**追記**  
`errno` の値と、`perror()` でエラーメッセージを表示させるようにサンプルを変更しました。  
`errno:12: Cannot allocate memory` と表示されましたが、メモリは 1GB以上空いてるので
メモリ不足ということはないと思います。  
**追記ここまで**

[code]

    // readdir() sample code
    // usage : programname directory
    #include        <stdio.h>
    #include        <dirent.h>
    #include        <errno.h>
    
    int main(int argc, char **argv) {
    
            struct  dirent  *entry;
            DIR     *dir;
            int     cnt = 0;
            char    errmsg[16];
    
            // 引数チェック
            if (argc <= 1) return 2;
    
            dir = opendir( argv[1] );
            if (dir == NULL) return 1;
            printf( "directory opened\n");
    
            while( (entry = readdir(dir)) != NULL) {
                    // ディレクトリ エントリーの名前を表示
                    printf("d_name: %s\n", entry->d_name);
                    cnt++;
            }
            // errno メッセージを表示
            sprintf(errmsg, "errno:%d", errno);
            perror(errmsg);
    
            closedir( dir );
            printf( "directory closed\n");
    
            // ディレクトリエントリの数を表示
            printf( "cnt = %d\n", cnt );
            return 0;
    }
    
[/code]

**コンパイル**

[code]

    $ gcc -m32 -o a.i686 sample.c
    $ gcc -o a.x86_64 sample.c
    
[/code]

**実行結果**

[code]

    $ ./a.x86_64 /mnt/cifs/
    directory opened
    d_name: .          ←ディレクトリの中身が参照できてる
    d_name: ..         ←ディレクトリの中身が参照できてる
    d_name: test.txt   ←ディレクトリの中身が参照できてる
    errno:0: Success
    directory closed
    cnt = 3            ←中身は 3件あった
    $ ./a.i686 /mnt/cifs/
    directory opened
    errno:12: Cannot allocate memory    ←メモリが確保できない？
    directory closed
    cnt = 0            ←中身が 0件となる
    
[/code]

**クライアント環境**

  * Linux datacos7 3.10.0-957.5.1.el7.x86_64 #1 SMP Fri Feb 1 14:54:57 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
  * CentOS Linux release 7.6.1810 (Core)
  * cifs-utils-6.2-10.el7.x86_64
  * gcc-4.8.5-36.el7.x86_64
  * glibc-2.17-260.el7_6.3 (i686とx86_64)

**サーバー環境**

  * Windows 2016 Server


CC BY-SA 4.0
2019-03-08T11:58:05.353
53298
2019-03-12T04:10:09.780
2019-03-10T02:33:35.770
5008
5008
question
linux c gcc
32bit 実行ファイルで cifs マウント先の readdir() が NULLになる


自己解決しました。

コンパイル時に `-D_FILE_OFFSET_BITS=64` をつけて実行すると正常に動きました。

[code]

    $ gcc -D_FILE_OFFSET_BITS=64 -m32  -o a64.i386 sample.c
    $ ./a64.i386 /mnt/cifs
    sizeof long: 4
    directory opened
    d_name: .
    d_name: ..
    d_name: test.txt
    errno:0: Success
    directory closed
    cnt = 3
    
[/code]

man feature_test_macros より引用

> _FILE_OFFSET_BITS  
>  このマクロを値 64 で定義すると、ファイル I/O とファイルシステム操作に 関連する 32 ビット版の関数とデータタイプは自動的に 64
> ビット版に 変換される。  
>  これは、32 ビットシステムで大きなファイル (> 2 ギガバイト) の I/O を実行する際に役立つ
> (このマクロを定義すると、コンパイルし直すだけで大きなファイルを 扱えるプログラムを書くことができる)。  
>  64 ビットシステムは、もともと 2 ギガバイトより大きなファイルを扱えるので、64 ビットシステムではこのマクロは効果を持たない。

dirent.hを見てみると `readdir64`と言うと、関数がありました。

このマクロを有効化してreaddirを呼び出すとreaddir64が実行されるっぽいです。


CC BY-SA 4.0
2019-03-12T03:09:17.493
53375
2019-03-12T04:10:09.780
2019-03-12T04:10:09.780
5008
5008
53298
answer