ftp.nice.ch/pub/next/unix/disk/ufs-NeXT.0.3.s.tar.gz#/linux/fs/ufs/namei.c

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.