リスト2(list_records.c、7ページ目にも掲載)はさらにnodeに接続し、recordを検索、表示させたものだ(図3)。35行目では、先ほどとは逆にこんどは/区切りの文字列からnodeを示すパスのリストを作成し、42行目ではこれを使ってnodeを指定し、接続を行っている。DirectoryService全体に接続するdirRefと、nodeに接続するnodeRefの2つは適宜必要になるため、現実に利用する場合は構造体やオブジェクトのインスタンス変数といった形で組にしてまとめて管理しておいたほうがいいだろう。

図3: list_records.c

図3: list_records.c

46行目ではやはりバッファを確保、さらに55~62行目で条件となる文字列を確保し、75行目のdsGetRecordListでrecordの検索を行っている。dsGetRecordListでは、以下の3つの条件を設定できる。

  • recordの名前
  • recordの形式
  • recordの読み出すattributeの一覧

55、58、61の各行で用いられているdsBuildListFromStringsAllocはその名前の通り、可変長引数を使って任意個数の文字列を渡して、確保したリストに格納した上で第2引数のポインタに返すという関数。このリストが条件を表すものになる。

例えば、55行目はrecordの名前を指定している。ここでは定数kDSRecordsAllだけを指定しているため、全てのrecordがマッチするようになっている。59行目はrecordの形式で、kDSStdRecordTypeUsersのため、ユーザアカウントを表すrecordのみがマッチされる。最後の61行目では、kDSAttributesAllを指定し、すべてのattributeを読み出すように指示している。

結果、そのnodeに存在する全ユーザアカウントのすべての属性情報を読み出すことになる。

先に挙げた3つの条件を変えることで特定の情報だけを読み出すこと可能だ。例えば、リスト3(list_records2.c、8ページ目にも掲載)では、recNamesにmeというユーザだけを指定している。このため、ユーザ名がmeとなるrecordだけが読み出される。

また、リスト4(list_records3.c、9ページ目にも掲載)では、今度はattributesをkDS1AttrDistinguishedName、 kDS1AttrGeneratedUID、 kDSNAttrMetaNodeLocation、 kDSNAttrAuthenticationAuthority の4つに限っている。

これらの情報は、あらかじめ呼び出し側が用意した、固定長のバッファに収めて渡されることを思い出してほしい。必要のないattributeの読み出しを控えることで、処理の手数を減らし性能を向上させることが可能だ(図4図5図6)。

図4: list_records.cでは、recordTypeは、ユーザアカウントの全レコードおよび全属性を取得

図5: list_records2.cでは、recNamesに文字列"me"を格納することで、meという名称のレコードのみを取得している

図6: list_records3.cでは、attrTypeにそれぞれの属性名の定数を格納することで、指定の属性だけを取得するようにしている

この検索で見つかるrecordは1つとは限らず、またrecordにはこの指定された1つ以上のattributeが格納されており、attributeは1つ以上の値を持ちえるため、87行目からの3重のループでデータを処理している。それぞれ読み出しをするたびにメモリが確保されるため、適切な開放関数を使って開放することを忘れないようにしよう(104、106、108行目)。

なお、そもそもどのnodeにrecordが格納されているか分からない場合はどうすべきかだが、ここで/Searchレコードを利用する。例えばリスト4を利用して、実行例13のように実行する。すると、全てのnode下のrecordを一気に検索でき、どのnodeにあってもrecordを見つけられる(図7)。さらにAppleMetaNodeLocationをみると、どのnodeにrecordが実際に格納されているのかが分かる。読み取りだけではなくattributeの編集を行いたい場合は、このAppleMetaNodeLocationの値を元にdsOpenDirNode関数を使ってあらためてnodeを開くといい。

実行例13: list_records3.cをビルド後、/Searchレコードを利用し検索

% cc -o list_records3 list_records3.c -framework DirectoryService
% ./list_records3 /Search | more|

図7: /Searchノードを使った実行結果。dsAttrTypeStandard:AppleMetaNodeLocationを確認することで、どのnodeにそのrecordが存在するか分かる。通常のMac OS XではたいていdsLocalにあるが、Mac OS X Serverの場合だと、OpenDirectoryサーバのLDAPv3にあるか、ローカルにあるかがこれで確認できる