系列文章 : [6.1810] 跟著 MIT 6.1810 學習基礎作業系統觀念
#define DIRSIZ 14
struct dirent {
ushort inum;
char name[DIRSIZ];
};
struct dirent 佔 16 bytesint
namecmp(const char *s, const char *t)
{
return strncmp(s, t, DIRSIZ);
}
比對檔案名稱,因為檔案名稱最長為 DIRSIZ,所以這邊 strncmp 的長度設為 DIRSIZ。
// Look for a directory entry in a directory.
// If found, set *poff to byte offset of entry.
struct inode*
dirlookup(struct inode *dp, char *name, uint *poff)
{
uint off, inum;
struct dirent de;
if(dp->type != T_DIR)
panic("dirlookup not DIR");
會去看該 inode 的類型是不是 directory
假如不是的話,就該馬上發出 panic。
for(off = 0; off < dp->size; off += sizeof(de)){
if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
panic("dirlookup read");
if(de.inum == 0)
continue;
if(namecmp(name, de.name) == 0){
// entry matches path element
if(poff)
*poff = off;
inum = de.inum;
return iget(dp->dev, inum);
}
}
return 0;
}
// Write a new directory entry (name, inum) into the directory dp.
// Returns 0 on success, -1 on failure (e.g. out of disk blocks).
int
dirlink(struct inode *dp, char *name, uint inum)
{
dp 這個 directory 裡面。 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;
}
dirlookup 裡面會去呼叫 iget,所以在這邊沒有要繼續使用該 inode 的話,需要自行 iput。 // Look for an empty dirent.
for(off = 0; off < dp->size; off += sizeof(de)){
if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
panic("dirlink read");
if(de.inum == 0)
break;
}
遍尋這個 directory 的所有 directory entry,找到有空位的地方,就把 off 記起來,並 break 退出迴圈。
strncpy(de.name, name, DIRSIZ);
de.inum = inum;
if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
return -1;
return 0;
}
把目標 inum 放在目標 directory entry 裡面。