fs.c int dirlink(struct inode *dp, char *name, uint inum)
トップページ
jupiteroak.hatenablog.com
fs.c
https://github.com/mit-pdos/xv6-public/blob/master/fs.c#L551
int dirlink(struct inode *dp, char *name, uint inum) { int off; struct dirent de; struct inode *ip; // Check that name is not present. if((ip = dirlookup(dp, name, 0)) != 0){ iput(ip); return -1; } // Look for an empty dirent. for(off = 0; off < dp->size; off += sizeof(de)){ if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) panic("dirlink read"); if(de.inum == 0) break; } strncpy(de.name, name, DIRSIZ); de.inum = inum; if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) panic("dirlink"); return 0; }
dirlink関数は、引数dpで指定されたiノード内にディレクトリエントリを作成し、引数nameで指定された名前のディレクトリと引数inumで指定された番号を持つiノードを対応させます。
引数 struct inode *dp
ディレクトリエントリが作成されるハードディスク上のiノードを表現したdinode構造体を指定するアドレスです。
引数 char *name
ディレクトリ名となる文字列データの先頭アドレスです。
引数 uint inum
ディレクトリに対応させるiノードのiノード番号です。
戻り値 0 または -1
ディレクトリエントリの作成に成功した場合は、0が戻り値となります。
引数nameで指定された名前のディレクトリが既に存在する場合は、-1が戻り値となります。
処理の内容
- iノードdpにディレクトリ名nameを含んだディレクトリエントリが存在しないことを確認する
- iノードdpから使用されていないディレクトリエントリを探す
- ディレクトリ名nameを含んだディレクトリエントリを作成する
- 0を戻り値としてリターンする
iノードdpにディレクトリ名nameを含んだディレクトリエントリが存在しないことを確認する
if((ip = dirlookup(dp, name, 0)) != 0){ iput(ip); return -1; }
dirlookup関数を呼び出して、iノードdpにディレクトリ名nameを含んだディレクトリエントリが存在しないことを確認します。
dirlookup関数は、iノードdpからディレクトリ名nameを含んだディレクトリエントリを探し、そのディレクトリ名に対応するiノードを取得します(iノードdpにおいて、ディレクトリ名nameを含んだディレクトリエントリの位置(バイトオフセット)を取得する必要がないので、第3引数を0にしています)。
(ip = dirlookup(dp, name, 0)) != 0 が真となる場合→dirlookup関数の戻り値が0ではない場合→iノードdpからディレクトリ名nameに対応するiノードが取得できてしまった場合は、iput関数を呼び出して、iノードの参照回数をデクリメントし(iノードの参照回数が0になった場合は、iノードを未使用状態に戻します)、-1を戻り値として処理を終了します。
iノードdpから使用されていないディレクトリエントリを探す
for(off = 0; off < dp->size; off += sizeof(de)){ ... }
iノードdpが所有するデータを、ディレクトリエントリのサイズ分(sizeof(de))ずつ、先頭から順番に読み込み、使用されていないディレクトリエントリ(dirent構造体)を探します(前述のdirlookup関数内でも、これと同じように、iノードdpが所有するデータを ディレクトリエントリのサイズ分(sizeof(de))ずつ 先頭から順番に読み込んで 探しているので、効率が悪い)。
ディレクトリエントリのサイズ分のデータを読み込む
if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) panic("dirlink read");
readi関数を呼び出して、iノードdpが所有するデータの範囲内において、引数offで指定された位置から、引数sizeof(de))で指定されたディレクトリエントリのサイズ分のデータを読み込み、その読み込んだデータを引数&deを先頭アドレスとするメモリ領域(dirent構造体の変数)に保存します。
readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)が真となる場合→readi関数がディレクトリエントリのサイズ分(sizeof(de))のデータを読み込めなかった場合は、panic関数を呼び出してメッセージを出力します。
ディレクトリ名nameを含んだディレクトリエントリを作成する
ディレクトリエントリにディレクトリ名nameを設定する
strncpy(de.name, name, DIRSIZ);
strcpy関数を呼び出して、ディレクトリエントリを表現したdirent構造体のnameメンバ(de.name)に、引数nameで指定された文字列データをコピーします。
0を戻り値としてリターンする
return 0;