MW211 EXIT

devlog
Apache/お気に入りアイコンエラー・前編
2013年05月08日
Apacheのエラーログに以下のようなメッセージが頻発している時がある。
┌──────────────────────────────────────┐
│[error] [client 127.0.0.1] File does not exist: C:/www/favicon.ico          │
└──────────────────────────────────────┘
と同時にアクセスログには以下が出力されている。
┌──────────────────────────────────────┐
│"GET /favicon.ico HTTP/1.1" 404 209                                         │
└──────────────────────────────────────┘

どうやら、ドキュメントルートの「favicon.ico」(お気に入りアイコン)を
探しにいって見つけられなかったようだ。

「favicon.ico」はHTML上に以下のように設定することにより
そのファイルをお気に入りアイコンとすることができるのだが、
そのApache管轄の設定がないページ(HTML)を開くとそうなるようだ。
┌──────────────────────────────────────┐
│<link rel="shortcut icon" href="favicon.ico"/>                              │
└──────────────────────────────────────┘

ブラウザで比較してみると、IE以外が軒並みエラーとなっている。
┌─┬────────────────────────────────────┐
│○│InternetExplorer(IE)                                                    │
├─┼────────────────────────────────────┤
│×│FireFox、Chrome、Safari、Opera                                          │
└─┴────────────────────────────────────┘

ということで、まとめると以下のような原因だった。
・「favicon.ico」を指定しないページはドキュメントルート配下の「favicon.ico」を
  そのページの「favicon.ico」と見なして読みに行く
  しかし、必要ないのでドキュメントロート配下に「favicon.ico」は置いていなかった
・IEの場合はお気に入り登録時のみ読みに行くが、他は開く都度読みに行く
  ということで、IE以外はページを開くたびに毎回エラーを誘発してしまう

そんな訳で、Apacheのエラーログにエラー出まくりなわけでよろしくない。

解決方法としては、ずばり「favicon.ico」をドキュメントルート直下に
置くというのがあるが、他にも設定で回避できそうだ。

詳しくは次回。つづく。
分類:Apache
C言語/readdir()とqsort()でscandir()を代用
2013年05月07日
「scandir()」は「opendir()、readdir()、closedir()、qsort()」を
まとめてやってくれる便利な関数だが、
「opendir()、readdir()、closedir()、qsort()」で同等のことをやるとしたら
以下のようになる。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【readdir()とqsort()を使用する例】
┌──────────────────────────────────────┐
│    typedef struct {                                                        │
│        char  name[256];                                                    │
│    } S_FILE;                                                               │
├──────────────────────────────────────┤
│    int            count   = 0;                                             │
│    DIR            *dir    = NULL;                                          │
│    struct dirent  *dirEnt = NULL;                                          │
│    S_FILE         dirFile[256];                                            │
├──────────────────────────────────────┤
│    dir = opendir(ディレクトリパス);    // オープン                         │
│    if (dir == NULL) {                                                      │
│        エラー処理;                                                         │
│    }                                                                       │
│    while (1) {                                                             │
│        dirEnt = readdir(dir);  // エントリ情報を取得                       │
│        if (dirEnt == NULL) {  // 取得終了                                  │
│            break;                                                          │
│        }                                                                   │
│        if (dirEnt->d_name[0] != '.') {  // 「.」「..」を除外する           │
│            continue;                                                       │
│        }                                                                   │
│        // ファイル名を取得                                                 │
│        snprintf(dirFile[count].name,                                       │
│                 sizeof(dirFile[count].name),                               │
│                 "%s",                                                      │
│                 dirEnt->d_name);                                           │
│        count++;                                                            │
│    }                                                                       │
│    closedir(dir);  // クローズ                                             │
├──────────────────────────────────────┤
│    // ソート                                                               │
│    qsort(&dirFile,                                // ソート対象            │
│          sizeof(dirFile) / (sizeof(dirFile[0])),  // 件数                  │
│          sizeof(dirFile[0]),                      // 一件あたりのサイズ    │
│          qsortComp);                              // qsort比較関数         │
└──────────────────────────────────────┘
「readdir()」の戻り値にて、「struct dirent」型のポインタに
エントリ情報(ファイル一覧)が取得される
戻り値が「NULL」(終了)となるまで順読みされる
#「readdir()」を使用するには前後に「opendir()」と「closedir()」が必要である
エントリ情報を配列等に採取し(その際、不要なものは読み飛ばししてしまう)、
最後に「qsort()」にて並び替えを行う
「qsort()」は構造体のソート(キーを基準に行ごとソートするような処理)も可能
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【qsort比較関数の例】(ファイル名で昇順・降順にを並び替える)
┌──────────────────────────────────────┐
│int  qsortComp(const void*  s1,                                             │
│               const void*  s2)                                             │
│{                                                                           │
│    if (昇順の場合) {                                                       │
│        return strcmp((char *)(((S_FILE *)s1)->name),                       │
│                      (char *)(((S_FILE *)s2)->name));                      │
│    } else {                                                                │
│        return strcmp((char *)(((S_FILE *)s2)->name),                       │
│                      (char *)(((S_FILE *)s1)->name));                      │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
「qsort()」の第四引数にて、関数を指定することでソート条件を指定できる
関数は別途自分で定義しなければならない(関数名は任意)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
分類:C/C++
C言語/scandir()の使い方
2013年05月06日
「scandir()」を使うと、指定したディレクトリ配下のファイル一覧情報を取得できる。
しかも、抽出や並び替えも同時に行うことができる。
いってみれば、「opendir()、readdir()、closedir()、qsort()」を
まとめてやってくれる便利か関数だ。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【scandir()を使用する例】
┌──────────────────────────────────────┐
│    struct dirent  **dirEnt;  // エントリ情報                               │
│    int  count = scandir(ディレクトリパス,  // ディレクトリを指定する       │
│                         &dirEnt,           // エントリ情報を取得する       │
│                         scanExtract,       // 抽出条件関数                 │
│                         scanSort);         // ソート条件関数               │
│    if (count < 0) {  // エラーの場合は件数が-1となる                       │
│        エラー処理;                                                         │
│    }                                                                       │
│    for (int i = 0; i < count; ++i) {                                       │
│        ここで「dirEnt[i]->d_name」を参照すればファイル名が取得できる;      │
│        free(dirEnt[i]);  // 個別に領域解放せねばならない                   │
│    }                                                                       │
│    free(dirEnt);  // 最後に全体を領域解放せねばならない                    │
└──────────────────────────────────────┘
「scandir()」の第二引数にて、「struct dirent」型のポインタに
エントリ情報(ファイル一覧)が取得される。
取得した件数は戻り値で取得できる(「-1」の場合はエラー)
あとはその一覧を参照するだけでよい。
ただし、「scandir()」内にて「malloc()」で領域を確保しているようなので
「free()」で解放しなければならない。
これは、ファイル一覧一件一件ごととそれらを統括する全体について
それぞれ行わなければならないようだ。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【抽出条件関数の例】(「.」「..」を除外する)
┌──────────────────────────────────────┐
│int  scanExtract(const struct dirent*  dir)                                 │
│{                                                                           │
│    return (dir->d_name[0] != '.');                                         │
│}                                                                           │
└──────────────────────────────────────┘
「scandir()」の第三引数にて、関数を指定することで抽出条件を指定できる。
関数は別途自分で定義しなければならない。(関数名は任意)
戻り値が「0」の場合は除外されることになる。
#上記の例でいえば、先頭が「.」から始まるファイル名は
  戻り値「false(=0)」となり除外される(それ以外は戻り値「true(=1)」)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【ソート条件関数の例】(ファイル名で昇順・降順にを並び替える)
┌──────────────────────────────────────┐
│int  scanSort(const void*  s1,                                              │
│              const void*  s2)                                              │
│{                                                                           │
│    if (昇順の場合) {                                                       │
│        return strcmp((*(struct dirent **)s1)->d_name,                      │
│                      (*(struct dirent **)s2)->d_name);                     │
│    } else {                                                                │
│        return strcmp((*(struct dirent **)s2)->d_name,                      │
│                      (*(struct dirent **)s1)->d_name);                     │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
「scandir()」の第四引数にて、関数を指定することでソート条件を指定できる。
関数は別途自分で定義しなければならない(関数名は任意)。
但し、ファイル名昇順のソートであれば「alphasort()」が
バージョン名昇順のソートであれば「versionsort()」という関数が用意されている。
#上記の場合は、ファイル名降順もサポートしたいので
  自前でファイル名のソートを実装した場合の例である
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
分類:C/C++
C言語/ファイルのフルパスを取得する方法
2013年05月05日
┌──────────────────────────────────────┐
│ls /aaa/bbb/*.txt                                                           │
└──────────────────────────────────────┘
上記みたいにフルパスで指定すれば、フルパスで結果が得られる
┌──────────────────────────────────────┐
│/aaa/bbb/ccc.txt                                                            │
└──────────────────────────────────────┘

でも、「/aaa/bbb」とかにいて、相対パスつまり「ls」ってだけコマンドを打つと
ファイル名しか取得できない。
┌──────────────────────────────────────┐
│ccc.txt                                                                     │
└──────────────────────────────────────┘

こういう場合は、以下のようにすればフルパスがとれるらしい。
┌──────────────────────────────────────┐
│find `pwd`                                                                  │
└──────────────────────────────────────┘

「find」コマンドに従って絞り込みもできる。
┌──────────────────────────────────────┐
│find `pwd` -name "ccc.txt"                                                  │
└──────────────────────────────────────┘

パイプを使うのもありだ。
┌──────────────────────────────────────┐
│find `pwd` | grep "ccc.txt"                                                 │
└──────────────────────────────────────┘

ちなみにディレクトリを指定するとその配下のファイル名のみが表示されるが。
┌──────────────────────────────────────┐
│ls ../aaa/bbb                                                               │
├──────────────────────────────────────┤
│ccc.txt                                                                     │
└──────────────────────────────────────┘

ワイルドカードで配下ファイルを指定してやると、そこまでのパスも表示されるようだ。
┌──────────────────────────────────────┐
│ls ../aaa/bbb/*                                                             │
├──────────────────────────────────────┤
│../aaa/bbb/ccc.txt                                                          │
└──────────────────────────────────────┘
分類:Linuxシェル
C言語/%sと空文字
2013年05月04日
「printf("%s",…」とかで使う、文字列がはめ込まれる「%s」。
これは、末尾の終端(\0)までを取り込むという仕様なので、
「\0」がない数値項目(int型とか)をぶちこんで例外となる場合がある。
#デバッグログなんかでよくやりがちなミスだ

それじゃ、NULL(\0)入れても大丈夫なんだろ、って早合点して
NULLを直接入れて例外となるのもありがちなミス
#って直接NULL入れる奇特な人は少数かもしれませんが、
  ポインタ変数の絡みで結果的にNULLが入るケースを放置してしまうことは結構ある
┌─┬────────────────────────────────────┐
│×│char*  s = NULL;                                                        │
│  │printf("%s", s);                                                        │
├─┼────────────────────────────────────┤
│○│char*  s = "";                                                          │
│  │printf("%s", s);                                                        │
└─┴────────────────────────────────────┘
「""」を入れるのは大丈夫なんだけどね。
「""」の場合は、ポインタで指したところが「\0」、
「NULL」の場合は、そもそも指すところがない、という違いなのだ。
分類:C/C++
Windows/拡張子しかないファイル名
2013年05月03日
Apacheの設定ファイル「.htaccess」とかは、「.」から始まる
いわば拡張子しかないファイル名である。

これらは、Explorerにおける「名前の変更」ではその名前に変更できない。
どうやら、不正なファイル名が生成されないように予防機能がついているようだ。

ということで、Windows上でこういうファイル名を生成する方法。
(1) コマンドプロンプト(DOSコマンド)からなら「RENAME」で名称変更できる。
  ┌────────────────────────────────────┐
  │RENAME 元のファイル名 .htaccess                                         │
  └────────────────────────────────────┘
    ちなみに、以下で空のファイルを生成できる。
  ┌────────────────────────────────────┐
  │ECHO > .htpasswd                                                        │
  └────────────────────────────────────┘
(2) エディタで名前をつけて保存する
    たいていのエディタでは特に制限がないから保存できるようだ

っていうか、ファイル名を変更とかしないで、
エディタで新規作成して名前を付けて保存するケースが多いから
あんまりこういうことに遭遇することはないというオチのような気がしてきた。
分類:Windows
SVN/実行権限
2013年05月01日
Linuxからシェル等を追加する場合には、その時点の実行権限で追加され、
チェックアウト(更新)やエクスポートするとその実行権限が初期設定される。

しかし、Windowsの場合は実行権限という概念自体がないので
「rw-r--r--」(644)の権限で登録されてしまう。

実行権限を登録したい場合には、プロパティを選び。
┌─────────────┐
│├SVN更新                 │
│├SVNコミット             │
│└TortoiseSVN             │
│  └プロパティ            │
└─────────────┘
そこから、「新規→実行形式」を選ぶ。
┌プロパティ───────────────────┐
│┌──────────────────────┐│
│└──────────────────────┘│
│┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐│
││    ││    ││    ││    ││    ││新規││
│└──┘└──┘└──┘└──┘└──┘└└実行形式
└────────────────────────┘
そこで「実行形式」のラジオボタンを有効とすればOK。
┌──────────────────────────┐
│【注意】このプロパティはWindowsでは効果がありません │
│  ●実行形式                                        │
│  ○非実行形式                                      │
│┌─────┐┌─────┐┌─────┐          │
││    OK    ││キャンセル││  ヘルプ  │          │
│└─────┘└─────┘└─────┘          │
└──────────────────────────┘
これで「rwxr-xr-x」(755)の権限となるので、このままコミットすればよい。

ただし、これをWindows上(TortoiseSVNとか)から、チェックアウト(更新)等しても
ダメで、Linuxコマンドでチェックアウト(更新)等して初めて権限が反映される。
ということに注意。
分類:SVN
前へ 1 2 3 次へ