This is namei.c in view mode; [Download] [Up]
/*
* linux/fs/ufs/namei.c
*
* Copyright (C) 1994 Yossi Gottlieb (yogo@math.tau.ac.il)
*
* Based on code and information:
* BSD code, Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved.
* linux/fs/minix Copyright (C) 1991, 1992, 1993 Linus Torvalds
*
*/
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/locks.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/bitops.h>
#include <linux/ufs_fs.h>
#include "ufs.h"
/*
* comment out this line if you want names > EXT2_NAME_LEN chars to be
* truncated. Else they will be disallowed.
*/
/* #define NO_TRUNCATE */
static inline int ufs_match(struct ufs_sb_info * sb,
int len, const char * name,
struct buffer_head * bh, unsigned long * offset)
{
struct ufs_dir_entry *de;
de = (struct ufs_dir_entry *) (bh->b_data + *offset);
*offset += dtohs(sb,de->d_reclen);
if (!de->d_ino || len != dtohs(sb,de->d_namlen))
return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (de->d_name[0]=='.') && (dtohs(sb,de->d_namlen)==1))
return 1;
return !memcmp(name,de->d_name, len);
}
/*
* finds an entry in the specified directory with the wanted name. It
* returns the cache buffer in which the entry was found, and the entry
* itself (as a parameter - res_dir). It does NOT read the inode of the
* entry - you'll have to do that yourself if you want to.
*/
static struct buffer_head * ufs_find_entry(struct inode * dir,
const char * name, int namelen, struct ufs_dir_entry ** res_dir)
{
unsigned long block, offset;
struct buffer_head * bh;
struct ufs_sb_info * sb;
*res_dir = NULL;
if (!dir || !dir->i_sb)
return NULL;
sb = &dir->i_sb->u.ufs_sb;
if (namelen > MAXNAMLEN) {
#ifdef NO_TRUNCATE
return NULL;
#else
namelen = MAXNAMLEN;
#endif
}
bh = NULL;
block = offset = 0;
while (block*BLOCK_SIZE+offset < dir->i_size) {
if (!bh) {
bh = ufs_bread(dir, numfrags(sb, block*BLOCK_SIZE+offset));
if (!bh) {
block++;
continue;
}
}
*res_dir = (struct ufs_dir_entry *) (bh->b_data + offset);
if (ufs_match(sb,namelen,name,bh,&offset))
return bh;
if (offset < bh->b_size)
continue;
brelse(bh);
bh = NULL;
offset = 0;
block++;
}
brelse(bh);
*res_dir = NULL;
return NULL;
}
int ufs_lookup(struct inode * dir,const char * name, int len,
struct inode ** result)
{
int ino;
struct ufs_dir_entry * de;
struct buffer_head * bh;
*result = NULL;
if (!dir)
return -ENOENT;
if (!S_ISDIR(dir->i_mode)) {
iput(dir);
return -ENOENT;
}
if (!(bh = ufs_find_entry(dir,name,len,&de))) {
iput(dir);
return -ENOENT;
}
ino = dtohl(&dir->i_sb->u.ufs_sb, de->d_ino);
brelse(bh);
if (!(*result = iget(dir->i_sb,ino))) {
iput(dir);
return -EACCES;
}
iput(dir);
return 0;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.