[Ocfs2-tools-commits] smushran commits r479 - in trunk: debugfs.ocfs2 debugfs.ocfs2/include libocfs2 libocfs2/include

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Fri Dec 10 20:28:27 CST 2004


Author: smushran
Date: 2004-12-10 20:28:25 -0600 (Fri, 10 Dec 2004)
New Revision: 479

Added:
   trunk/libocfs2/namei.c
Modified:
   trunk/debugfs.ocfs2/commands.c
   trunk/debugfs.ocfs2/include/main.h
   trunk/debugfs.ocfs2/include/utils.h
   trunk/debugfs.ocfs2/utils.c
   trunk/libocfs2/Makefile
   trunk/libocfs2/include/ocfs2.h
   trunk/libocfs2/ocfs2_err.et.in
Log:
namei.c added in libocfs2 to parse pathnames
ls/cd/chroot added in debugfs

Modified: trunk/debugfs.ocfs2/commands.c
===================================================================
--- trunk/debugfs.ocfs2/commands.c	2004-12-11 02:10:10 UTC (rev 478)
+++ trunk/debugfs.ocfs2/commands.c	2004-12-11 02:28:25 UTC (rev 479)
@@ -62,6 +62,7 @@
 static void do_journal (char **args);
 static void do_group (char **args);
 static void do_extent (char **args);
+static void do_chroot (char **args);
 
 extern gboolean allow_write;
 
@@ -74,6 +75,7 @@
   { "cd",     do_cd     },
   { "ls",     do_ls     },
   { "pwd",    do_pwd    },
+  { "chroot", do_chroot },
 
   { "mkdir",  do_mkdir  },
   { "rmdir",  do_rmdir  },
@@ -152,6 +154,51 @@
 }					/* do_command */
 
 /*
+ * check_device_open()
+ *
+ */
+static int check_device_open(void)
+{
+	if (!gbls.fs) {
+		fprintf(stderr, "Device not open\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * process_inode_args()
+ *
+ */
+static int process_inode_args(char **args, uint64_t *blkno)
+{
+	errcode_t ret;
+
+	if (check_device_open())
+		return -1;
+
+	if (!args[1]) {
+		fprintf(stderr, "usage: %s [filespec]\n", args[0]);
+		return -1;
+	}
+
+	ret = string_to_inode(gbls.fs, gbls.root_blkno, gbls.cwd_blkno,
+			      args[1], blkno);
+	if (ret) {
+		com_err(gbls.progname, ret, "");
+		return -1;
+	}
+
+	if (*blkno >= gbls.max_blocks) {
+		fprintf(stderr, "Block number is larger than volume size\n");
+		ret = -1;
+	}
+
+	return 0;
+}
+
+/*
  * get_blknum()
  *
  */
@@ -179,25 +226,24 @@
  * get_nodenum()
  *
  */
-static errcode_t get_nodenum(char *nodestr, uint16_t *nodenum)
+static int get_nodenum(char **args, uint16_t *nodenum)
 {
-	errcode_t ret = OCFS2_ET_INVALID_ARGUMENT;
 	ocfs2_super_block *sb = OCFS2_RAW_SB(gbls.fs->fs_super);
 	char *endptr;
 
-	if (nodestr) {
-		*nodenum = strtoul(nodestr, &endptr, 0);
+	if (args[1]) {
+		*nodenum = strtoul(args[1], &endptr, 0);
 		if (!*endptr) {
 			if (*nodenum < sb->s_max_nodes)
-				ret = 0;
+				return 0;
 			else
-				printf("node number is too large\n");
+				fprintf(stderr, "Node number is too large\n");
 		} else
-			printf("Invalid node number\n");
+			fprintf(stderr, "usage: %s [nodenum]\n", args[0]);
 	} else
-		printf("no node number specified\n");
+		fprintf(stderr, "usage: %s [nodenum]\n", args[0]);
 
-	return ret;
+	return -1;
 }
 
 /*
@@ -304,8 +350,8 @@
 		do_close (NULL);
 
 	if (dev == NULL) {
-		printf ("no device specified\n");
-		goto bail;
+		fprintf (stderr, "usage: %s [device]\n", args[0]);
+		return ;
 	}
 
 	flags = allow_write ? OCFS2_FLAG_RW : OCFS2_FLAG_RO;
@@ -313,14 +359,14 @@
 	if (ret) {
 		gbls.fs = NULL;
 		com_err(gbls.progname, ret, "while opening \"%s\"", dev);
-		goto bail;
+		return ;
 	}
 
 	/* allocate blocksize buffer */
 	ret = ocfs2_malloc_block(gbls.fs->fs_io, &gbls.blockbuf);
 	if (ret) {
 		com_err(gbls.progname, ret, "while allocating a block");
-		goto bail;
+		return ;
 	}
 
 	sb = OCFS2_RAW_SB(gbls.fs->fs_super);
@@ -331,10 +377,10 @@
 	gbls.max_blocks = ocfs2_clusters_to_blocks(gbls.fs, gbls.max_clusters);
 	gbls.root_blkno = sb->s_root_blkno;
 	gbls.sysdir_blkno = sb->s_system_dir_blkno;
-	gbls.curdir_blkno = sb->s_root_blkno;
-	if (gbls.curdir)
-		free(gbls.curdir);
-	gbls.curdir = strdup("/");
+	gbls.cwd_blkno = sb->s_root_blkno;
+	if (gbls.cwd)
+		free(gbls.cwd);
+	gbls.cwd = strdup("/");
 
 	/* lookup heartbeat file */
 	snprintf (sysfile, sizeof(sysfile),
@@ -354,7 +400,6 @@
 			gbls.jrnl_blkno[i] = 0;
 	}
 
-bail:
 	return ;
 	
 }					/* do_open */
@@ -367,10 +412,8 @@
 {
 	errcode_t ret = 0;
 
-	if (!gbls.device) {
-		printf ("device not open\n");
+	if (check_device_open())
 		return ;
-	}
 
 	ret = ocfs2_close(gbls.fs);
 	if (ret)
@@ -392,61 +435,76 @@
  */
 static void do_cd (char **args)
 {
+	uint64_t blkno;
+	errcode_t ret;
 
+	if (process_inode_args(args, &blkno))
+		return ;
+
+	ret = ocfs2_check_directory(gbls.fs, blkno);
+	if (ret) {
+		com_err(gbls.progname, ret, "");
+		return ;
+	}
+
+	gbls.cwd_blkno = blkno;
+
+	return ;
 }					/* do_cd */
 
 /*
+ * do_chroot()
+ *
+ */
+static void do_chroot (char **args)
+{
+	uint64_t blkno;
+	errcode_t ret;
+
+	if (process_inode_args(args, &blkno))
+		return ;
+
+	ret = ocfs2_check_directory(gbls.fs, blkno);
+	if (ret) {
+		com_err(gbls.progname, ret, "");
+		return ;
+	}
+
+	gbls.root_blkno = blkno;
+
+	return ;
+}
+
+/*
  * do_ls()
  *
  */
 static void do_ls (char **args)
 {
-	ocfs2_dinode *di;
 	uint64_t blkno;
-	char *buf = NULL;
 	FILE *out = NULL;
 	errcode_t ret = 0;
 
-	if (!gbls.fs) {
-		printf ("device not open\n");
-		goto bail;
-	}
+	if (process_inode_args(args, &blkno))
+		return ;
 
-	if (args[1]) {
-		ret = get_blknum(args[1], &blkno);
-		if (ret)
-			goto bail;
-	} else
-		blkno = gbls.curdir_blkno;
-
-	buf = gbls.blockbuf;
-	ret = ocfs2_read_inode(gbls.fs, blkno, buf);
+	ret = ocfs2_check_directory(gbls.fs, blkno);
 	if (ret) {
-		com_err(gbls.progname, ret, "while reading inode %"PRIu64, blkno);
-		goto bail;
+		com_err(gbls.progname, ret, "");
+		return ;
 	}
 
-	di = (ocfs2_dinode *)buf;
-
-	if (!S_ISDIR(di->i_mode)) {
-		printf("Not a dir\n");
-		goto bail;
-	}
-
 	out = open_pager ();
 	fprintf(out, "\t%-15s %-4s %-4s %-2s %-4s\n",
 		"Inode", "Rlen", "Nlen", "Ty", "Name");
 
 	ret = ocfs2_dir_iterate(gbls.fs, blkno, 0, NULL,
 				dump_dir_entry, out);
-	if (ret) {
+	if (ret)
 		com_err(gbls.progname, ret,
 			"while listing inode %"PRIu64" on \"%s\"\n",
 			blkno, gbls.device);
-		goto bail;
-	}
 
-bail:
 	close_pager (out);
 
 	return ;
@@ -458,7 +516,7 @@
  */
 static void do_pwd (char **args)
 {
-	printf ("%s\n", gbls.curdir ? gbls.curdir : "No dir");
+	printf ("%s\n", __FUNCTION__);
 }					/* do_pwd */
 
 /*
@@ -512,23 +570,25 @@
  */
 static void do_help (char **args)
 {
-	printf ("curdev\t\t\t\tShow current device\n");
-	printf ("open <device>\t\t\tOpen a device\n");
-	printf ("close\t\t\t\tClose a device\n");
-	printf ("show_super_stats, stats [-h]\tShow superblock\n");
-	printf ("show_inode_info, stat <blknum>\tShow inode\n");
-	printf ("pwd\t\t\t\tPrint working directory\n");
-	printf ("ls <blknum>\t\t\tList directory\n");
-	printf ("cat <blknum> [outfile]\t\tPrints or concatenates file to stdout/outfile\n");
-	printf ("dump <blknum> <outfile>\t\tDumps file to outfile\n");
-	printf ("nodes\t\t\t\tList of nodes\n");
-	printf ("publish\t\t\t\tPublish blocks\n");
-	printf ("vote\t\t\t\tVote blocks\n");
-	printf ("logdump <nodenum>\t\tPrints journal file for the node\n");
-	printf ("extent <blknum>\t\t\tShow extent block\n");
-	printf ("group <blknum>\t\t\tShow chain group\n");
-	printf ("help, ?\t\t\t\tThis information\n");
-	printf ("quit, q\t\t\t\tExit the program\n");
+	printf ("curdev\t\t\tShow current device\n");
+	printf ("open\t\t\tOpen a device\n");
+	printf ("close\t\t\tClose a device\n");
+	printf ("show_super_stats, stats\tShow superblock\n");
+	printf ("show_inode_info, stat\tShow inode\n");
+//	printf ("pwd\t\t\t\tPrint working directory\n");
+	printf ("ls\t\t\tList directory\n");
+	printf ("cd\t\t\tChange directory\n");
+	printf ("chroot\t\t\tChange root\n");
+//	printf ("cat <blknum> [outfile]\t\tPrints or concatenates file to stdout/outfile\n");
+//	printf ("dump <blknum> <outfile>\t\tDumps file to outfile\n");
+//	printf ("nodes\t\t\t\tList of nodes\n");
+//	printf ("publish\t\t\t\tPublish blocks\n");
+//	printf ("vote\t\t\t\tVote blocks\n");
+	printf ("logdump\t\t\tPrints journal file for the node\n");
+	printf ("extent\t\t\tShow extent block\n");
+	printf ("group\t\t\tShow chain group\n");
+	printf ("help, ?\t\t\tThis information\n");
+	printf ("quit, q\t\t\tExit the program\n");
 }					/* do_help */
 
 /*
@@ -571,10 +631,8 @@
 	ocfs2_dinode *in;
 	ocfs2_super_block *sb;
 
-	if (!gbls.fs) {
-		printf ("device not open\n");
+	if (check_device_open())
 		goto bail;
-	}
 
 	out = open_pager ();
 	in = gbls.fs->fs_super;
@@ -602,21 +660,15 @@
 	FILE *out;
 	errcode_t ret = 0;
 
-	if (!gbls.fs) {
-		printf ("device not open\n");
-		goto bail;
-	}
+	if (process_inode_args(args, &blkno))
+		return ;
 
-	ret = get_blknum(args[1], &blkno);
-	if (ret)
-		goto bail;
-
 	buf = gbls.blockbuf;
 	ret = ocfs2_read_inode(gbls.fs, blkno, buf);
 	if (ret) {
 		com_err(gbls.progname, ret,
 			"while reading inode in block %"PRIu64, blkno);
-		goto bail;
+		return ;
 	}
 
 	inode = (ocfs2_dinode *)buf;
@@ -633,8 +685,6 @@
 
 	close_pager(out);
 
-bail:
-
 	return ;
 }					/* do_inode */
 
@@ -650,10 +700,8 @@
 	errcode_t ret;
 	void (*dump_func) (FILE *out, char *buf);
 
-	if (!gbls.fs) {
-		printf ("device not open\n");
-		goto bail;
-	}
+	if (check_device_open())
+		return ;
 
 	DBGFS_FATAL("internal");
 
@@ -680,6 +728,7 @@
  */
 static void do_dump (char **args)
 {
+#if 0
 	uint64_t blkno = 0;
 	int32_t outfd = -1;
 	FILE *out = NULL;
@@ -725,7 +774,7 @@
 	
 	if (outfd > 2)
 		close (outfd);
-
+#endif
 	return ;
 }					/* do_dump */
 
@@ -742,14 +791,11 @@
 	uint16_t nodenum;
 	errcode_t ret = 0;
 
-	if (!gbls.fs) {
-		printf ("device not open\n");
-		goto bail;
-	}
+	if (check_device_open())
+		return ;
 
-	ret = get_nodenum(args[1], &nodenum);
-	if (ret)
-		goto bail;
+	if (get_nodenum(args, &nodenum))
+		return ;
 
 	blkno = gbls.jrnl_blkno[nodenum];
 
@@ -783,15 +829,9 @@
 	errcode_t ret = 0;
 	int index = 0;
 
-	if (!gbls.fs) {
-		printf ("device not open\n");
-		goto bail;
-	}
+	if (process_inode_args(args, &blkno))
+		return ;
 
-	ret = get_blknum(args[1], &blkno);
-	if (ret)
-		goto bail;
-
 	buf = gbls.blockbuf;
 
 	out = open_pager();
@@ -800,7 +840,8 @@
 		if (ret) {
 			com_err(gbls.progname, ret,
 				"while reading chain group in block %"PRIu64, blkno);
-			goto close;
+			close_pager (out);
+			return ;
 		}
 
 		grp = (ocfs2_group_desc *)buf;
@@ -808,9 +849,8 @@
 		blkno = grp->bg_next_group;
 		index++;
 	}
-close:
+
 	close_pager (out);
-bail:
 
 	return ;
 }					/* do_group */
@@ -827,37 +867,24 @@
 	FILE *out;
 	errcode_t ret = 0;
 
-	if (!gbls.fs) {
-		printf ("device not open\n");
-		goto bail;
-	}
+	if (process_inode_args(args, &blkno))
+		return ;
 
-	ret = get_blknum(args[1], &blkno);
-	if (ret)
-		goto bail;
-
 	buf = gbls.blockbuf;
 	ret = ocfs2_read_extent_block(gbls.fs, blkno, buf);
 	if (ret) {
 		com_err(gbls.progname, ret,
 			"while reading extent in block %"PRIu64, blkno);
-		goto bail;
+		return ;
 	}
 
 	eb = (ocfs2_extent_block *)buf;
-	if (memcmp(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE,
-		   sizeof(OCFS2_EXTENT_BLOCK_SIGNATURE))) {
-		printf("Not an extent block\n");
-		goto bail;
-	}
 
 	out = open_pager();
 	dump_extent_block(out, eb);
 	dump_extent_list(out, &eb->h_list);
 	close_pager(out);
 
-bail:
-
 	return ;
 }					/* do_extent */
 

Modified: trunk/debugfs.ocfs2/include/main.h
===================================================================
--- trunk/debugfs.ocfs2/include/main.h	2004-12-11 02:10:10 UTC (rev 478)
+++ trunk/debugfs.ocfs2/include/main.h	2004-12-11 02:28:25 UTC (rev 479)
@@ -69,8 +69,8 @@
 	char *progname;
 	char *device;
 	ocfs2_filesys *fs;
-	char *curdir;
-	uint64_t curdir_blkno;
+	char *cwd;
+	uint64_t cwd_blkno;
 	char *blockbuf;
 	uint64_t max_clusters;
 	uint64_t max_blocks;

Modified: trunk/debugfs.ocfs2/include/utils.h
===================================================================
--- trunk/debugfs.ocfs2/include/utils.h	2004-12-11 02:10:10 UTC (rev 478)
+++ trunk/debugfs.ocfs2/include/utils.h	2004-12-11 02:28:25 UTC (rev 479)
@@ -26,13 +26,13 @@
 #ifndef __UTILS_H__
 #define __UTILS_H__
 
-void add_extent_rec (GArray *arr, ocfs2_extent_rec *rec);
-void add_dir_rec (GArray *arr, struct ocfs2_dir_entry *rec);
 void get_vote_flag (__u32 flag, GString *str);
 void get_publish_flag (__u32 flag, GString *str);
 void get_journal_blktyp (__u32 jtype, GString *str);
 void get_tag_flag (__u32 flags, GString *str);
 FILE *open_pager(void);
 void close_pager(FILE *stream);
+errcode_t string_to_inode(ocfs2_filesys *fs, uint64_t root_blkno,
+			  uint64_t cwd_blkno, char *str, uint64_t *blkno);
 
 #endif		/* __UTILS_H__ */

Modified: trunk/debugfs.ocfs2/utils.c
===================================================================
--- trunk/debugfs.ocfs2/utils.c	2004-12-11 02:10:10 UTC (rev 478)
+++ trunk/debugfs.ocfs2/utils.c	2004-12-11 02:28:25 UTC (rev 479)
@@ -26,54 +26,6 @@
 #include <main.h>
 
 /*
- * add_extent_rec()
- *
- */
-void add_extent_rec (GArray *arr, ocfs2_extent_rec *rec)
-{
-	ocfs2_extent_rec *new;
-
-	if (!arr)
-		return ;
-
-	if (!(new = malloc(sizeof(ocfs2_extent_rec))))
-		DBGFS_FATAL("%s", strerror(errno));
-
-	memcpy(new, rec, sizeof(ocfs2_extent_rec));
-	g_array_append_vals(arr, new, 1);
-
-	return ;
-}				/* add_extent_rec */
-
-/*
- * add_dir_rec()
- *
- */
-void add_dir_rec (GArray *arr, struct ocfs2_dir_entry *rec)
-{
-	struct ocfs2_dir_entry *new;
-
-	if (!arr)
-		return ;
-
-	if (!(new = malloc(sizeof(struct ocfs2_dir_entry))))
-		DBGFS_FATAL("%s", strerror(errno));
-
-	memset(new, 0, sizeof(struct ocfs2_dir_entry));
-
-	new->inode = rec->inode;
-	new->rec_len = rec->rec_len;
-	new->name_len = rec->name_len;
-	new->file_type = rec->file_type;
-	strncpy(new->name, rec->name, rec->name_len);
-	new->name[rec->name_len] = '\0';
-
-	g_array_append_vals(arr, new, 1);
-
-	return ;
-}				/* add_dir_rec */
-
-/*
  * get_vote_flag()
  *
  */
@@ -103,7 +55,7 @@
 		g_string_append (str, "none");
 
 	return ;
-}				/* get_vote_flag */
+}
 
 /*
  * get_publish_flag()
@@ -189,7 +141,7 @@
 		g_string_append (str, "none");
 
 	return ;
-}				/* get_publish_flag */
+}
 
 /*
  * get_journal_blktyp()
@@ -219,7 +171,7 @@
 		g_string_append (str, "none");
 
 	return ;
-}				/* get_journal_blktyp */
+}
 
 /*
  * get_tag_flag()
@@ -246,7 +198,7 @@
 
 done:
 	return ;
-}				/* get_tag_flag */
+}
 
 /*
  * open_pager() -- copied from e2fsprogs-1.32/debugfs/util.c
@@ -271,7 +223,7 @@
 	outfile = popen(pager, "w");
 
 	return (outfile ? outfile : stdout);
-}				/* open_pager */
+}
 
 /*
  * close_pager() -- copied from e2fsprogs-1.32/debugfs/util.c
@@ -282,4 +234,34 @@
 void close_pager(FILE *stream)
 {
 	if (stream && stream != stdout) pclose(stream);
-}				/* close_pager */
+}
+
+
+/*
+ * string_to_inode()
+ *
+ * This routine is used whenever a command needs to turn a string into
+ * an inode.
+ *
+ * Copyright (C) 1993, 1994 Theodore Ts'o.  This file may be
+ * redistributed under the terms of the GNU Public License.
+ */
+errcode_t string_to_inode(ocfs2_filesys *fs, uint64_t root_blkno,
+			  uint64_t cwd_blkno, char *str, uint64_t *blkno)
+{
+	int len;
+	char *end;
+
+	/*
+	 * If the string is of the form <ino>, then treat it as an
+	 * inode number.
+	 */
+	len = strlen(str);
+	if ((len > 2) && (str[0] == '<') && (str[len-1] == '>')) {
+		*blkno = strtoul(str+1, &end, 0);
+		if (*end=='>')
+			return 0;
+	}
+
+	return ocfs2_namei(fs, root_blkno, cwd_blkno, str, blkno);
+}

Modified: trunk/libocfs2/Makefile
===================================================================
--- trunk/libocfs2/Makefile	2004-12-11 02:10:10 UTC (rev 478)
+++ trunk/libocfs2/Makefile	2004-12-11 02:28:25 UTC (rev 479)
@@ -66,7 +66,8 @@
 	bitops.c	\
 	expanddir.c	\
 	newdir.c	\
-	extend_file.c
+	extend_file.c	\
+	namei.c
 
 HFILES =				\
 	include/jfs_user.h		\

Modified: trunk/libocfs2/include/ocfs2.h
===================================================================
--- trunk/libocfs2/include/ocfs2.h	2004-12-11 02:10:10 UTC (rev 478)
+++ trunk/libocfs2/include/ocfs2.h	2004-12-11 02:28:25 UTC (rev 479)
@@ -513,6 +513,18 @@
 			      uint32_t len,
 			      uint64_t start_blkno);
 
+errcode_t ocfs2_lookup(ocfs2_filesys *fs, uint64_t dir, const char *name,
+		       int namelen, char *buf, uint64_t *inode);
+
+errcode_t ocfs2_namei(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
+		      const char *name, uint64_t *inode);
+
+errcode_t ocfs2_namei_follow(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
+			     const char *name, uint64_t *inode);
+
+errcode_t ocfs2_follow_link(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
+			    uint64_t inode, uint64_t *res_inode);
+
 /* 
  * ${foo}_to_${bar} is a floor function.  blocks_to_clusters will
  * returns the cluster that contains a block, not the number of clusters

Added: trunk/libocfs2/namei.c
===================================================================
--- trunk/libocfs2/namei.c	2004-12-11 02:10:10 UTC (rev 478)
+++ trunk/libocfs2/namei.c	2004-12-11 02:28:25 UTC (rev 479)
@@ -0,0 +1,268 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * namei.c
+ *
+ * ocfs2 directory lookup operations
+ *
+ * Copyright (C) 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2,  as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * This code is a port of e2fsprogs/lib/ext2fs/namei.c
+ * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
+ */
+
+#define _XOPEN_SOURCE 600 /* Triggers magic in features.h */
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ocfs2.h"
+
+static errcode_t open_namei(ocfs2_filesys *fs, uint64_t root, uint64_t base,
+			    const char *pathname, size_t pathlen, int follow,
+			    int link_count, char *buf, uint64_t *res_inode);
+
+/*
+ * follow_link()
+ *
+ */
+static errcode_t follow_link(ocfs2_filesys *fs, uint64_t root, uint64_t dir,
+			     uint64_t inode, int link_count,
+			     char *buf, uint64_t *res_inode)
+{
+	char *pathname;
+	char *buffer = NULL;
+	errcode_t ret;
+	ocfs2_dinode *di = NULL;
+	ocfs2_extent_list *el;
+	uint64_t blkno;
+
+#ifdef NAMEI_DEBUG
+	printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
+	       root, dir, inode, link_count);
+	
+#endif
+
+	ret = ocfs2_malloc_block(fs->fs_io, (void **)&di);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_read_inode(fs, inode, (char *)di);
+	if (ret)
+		goto bail;
+
+	if (!S_ISLNK(di->i_mode)) {
+		*res_inode = inode;
+		ret = 0;
+		goto bail;
+	}
+
+	if (link_count++ > 5) {
+		ret = OCFS2_ET_SYMLINK_LOOP;
+		goto bail;
+	}
+
+	el = &(di->id2.i_list);
+
+	if (!di->i_clusters || !el->l_next_free_rec) {
+		ret = OCFS2_ET_INTERNAL_FAILURE;
+		goto bail;
+	}
+
+	blkno = el->l_recs[0].e_blkno;
+
+	ret = ocfs2_malloc_block(fs->fs_io, (void **) &buffer);
+	if (ret)
+		goto bail;
+
+	ret = io_read_block(fs->fs_io, blkno, 1, buffer);
+	if (ret)
+		goto bail;
+
+	pathname = buffer;
+
+	ret = open_namei(fs, root, dir, pathname, di->i_size, 1,
+			 link_count, buf, res_inode);
+
+bail:
+	if (buffer)
+		ocfs2_free((void **) &buffer);
+
+	if (di)
+		ocfs2_free(&di);
+
+	return ret;
+}
+
+/*
+ * dir_namei()
+ *
+ * This routine interprets a pathname in the context of the current
+ * directory and the root directory, and returns the inode of the
+ * containing directory, and a pointer to the filename of the file
+ * (pointing into the pathname) and the length of the filename.
+ */
+static errcode_t dir_namei(ocfs2_filesys *fs, uint64_t root, uint64_t dir,
+			   const char *pathname, int pathlen,
+			   int link_count, char *buf,
+			   const char **name, int *namelen,
+			   uint64_t *res_inode)
+{
+	char c;
+	const char *thisname;
+	int len;
+	uint64_t inode;
+	errcode_t ret;
+
+	if ((c = *pathname) == '/') {
+        	dir = root;
+		pathname++;
+		pathlen--;
+	}
+	while (1) {
+        	thisname = pathname;
+		for (len=0; --pathlen >= 0;len++) {
+			c = *(pathname++);
+			if (c == '/')
+				break;
+		}
+
+		if (pathlen < 0)
+			break;
+
+		ret = ocfs2_lookup (fs, dir, thisname, len, buf, &inode);
+		if (ret)
+			return ret;
+
+        	ret = follow_link (fs, root, dir, inode, link_count, buf, &dir);
+        	if (ret)
+			return ret;
+    	}
+
+	*name = thisname;
+	*namelen = len;
+	*res_inode = dir;
+	return 0;
+}
+
+/*
+ * open_namei()
+ *
+ */
+static errcode_t open_namei(ocfs2_filesys *fs, uint64_t root, uint64_t base,
+			    const char *pathname, size_t pathlen, int follow,
+			    int link_count, char *buf, uint64_t *res_inode)
+{
+	const char *basename;
+	int namelen;
+	uint64_t dir, inode;
+	errcode_t ret;
+
+#ifdef NAMEI_DEBUG
+	printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n",
+	       root, base, pathlen, pathname, link_count);
+#endif
+	ret = dir_namei(fs, root, base, pathname, pathlen,
+			   link_count, buf, &basename, &namelen, &dir);
+	if (ret)
+		return ret;
+
+	if (!namelen) {                     /* special case: '/usr/' etc */
+		*res_inode=dir;
+		return 0;
+	}
+
+	ret = ocfs2_lookup (fs, dir, basename, namelen, buf, &inode);
+	if (ret)
+		return ret;
+
+	if (follow) {
+		ret = follow_link(fs, root, dir, inode, link_count, buf, &inode);
+		if (ret)
+			return ret;
+	}
+#ifdef NAMEI_DEBUG
+	printf("open_namei: (link_count=%d) returns %lu\n",
+	       link_count, inode);
+#endif
+	*res_inode = inode;
+	return 0;
+}
+
+/*
+ * ocfs2_namei()
+ *
+ */
+errcode_t ocfs2_namei(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
+		      const char *name, uint64_t *inode)
+{
+	char *buf;
+	errcode_t ret;
+	
+	ret = ocfs2_malloc_block(fs->fs_io, (void **) &buf);
+	if (ret)
+		return ret;
+
+	ret = open_namei(fs, root, cwd, name, strlen(name), 0, 0, buf, inode);
+
+	ocfs2_free((void **) &buf);
+	return ret;
+}
+
+/*
+ * ocfs2_namei_follow()
+ *
+ */
+errcode_t ocfs2_namei_follow(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
+			     const char *name, uint64_t *inode)
+{
+	char *buf;
+	errcode_t ret;
+	
+	ret = ocfs2_malloc_block(fs->fs_io, (void **) &buf);
+	if (ret)
+		return ret;
+	
+	ret = open_namei(fs, root, cwd, name, strlen(name), 1, 0, buf, inode);
+
+	ocfs2_free((void **) &buf);
+	return ret;
+}
+
+/*
+ * ocfs2_follow_link()
+ *
+ */
+errcode_t ocfs2_follow_link(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
+			    uint64_t inode, uint64_t *res_inode)
+{
+	char *buf;
+	errcode_t ret;
+	
+	ret = ocfs2_malloc_block(fs->fs_io, (void **) &buf);
+	if (ret)
+		return ret;
+
+	ret = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
+
+	ocfs2_free((void **) &buf);
+	return ret;
+}

Modified: trunk/libocfs2/ocfs2_err.et.in
===================================================================
--- trunk/libocfs2/ocfs2_err.et.in	2004-12-11 02:10:10 UTC (rev 478)
+++ trunk/libocfs2/ocfs2_err.et.in	2004-12-11 02:28:25 UTC (rev 479)
@@ -144,4 +144,7 @@
 ec	OCFS2_ET_ITERATION_COMPLETE,
 	"Iteration complete"
 
+ec	OCFS2_ET_SYMLINK_LOOP,
+	"Too many symbolic links encountered"
+
 	end



More information about the Ocfs2-tools-commits mailing list