structinode { uint dev; // Device number uint inum; // Inode number int ref; // Reference count structsleeplocklock;// protects everything below here int valid; // inode has been read from disk? short type; // copy of disk inode short major; short minor; short nlink; uint size; uint addrs[NDIRECT + 1]; };
// On-disk inode structure structdinode { short type; // File type short major; // Major device number (T_DEVICE only) short minor; // Minor device number (T_DEVICE only) short nlink; // Number of links to inode in file system uint size; // Size of file (bytes) uint addrs[NDIRECT + 2]; // Data block addresses };
uint64 sys_symlink(void) { char target[MAXPATH]; // The target that the symlink refers to. char path[MAXPATH]; // The path where the symlink is created. argstr(0, target, MAXPATH); argstr(1, path, MAXPATH);
// Create a new inode; or open an existing inode // with the path specified. if(omode & O_CREATE){ ip = create(path, T_FILE, 0, 0); if(ip == 0){ end_op(); return-1; } } else { if((ip = namei(path)) == 0){ end_op(); return-1; } ilock(ip); if(ip->type == T_DIR && omode != O_RDONLY){ iunlockput(ip); end_op(); return-1; } } if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){ iunlockput(ip); end_op(); return-1; }
// Redirect to the real inode, if the path is a symlink // and opened without a O_NOFOLLOW. // For symlink path opened with O_NOFOLLOW, we won't recursively step into the inode // that said symlink refers to. if (ip->type == T_SYMLINK && !(omode & O_NOFOLLOW)) { for (int dep = 0; dep < 10 && ip->type == T_SYMLINK; ++dep) { char path[MAXPATH]; memset(path, 0, sizeof path); readi(ip, 0, (uint64)path, 0, MAXPATH); // Release the current inode since we'll go ahead. iunlockput(ip); // Try to look up the next inode. if ((ip = namei(path)) == 0) { end_op(); return-1; }
ilock(ip); }
// Returns an error code if the depth of links reaches some threshold (10). if (ip->type == T_SYMLINK) { iunlockput(ip); end_op(); return-1; } }