1/* vi: set sw=4 ts=4: */ 2/* 3 * get_pathname.c --- do directry/inode -> name translation 4 * 5 * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. 6 * 7 * %Begin-Header% 8 * This file may be redistributed under the terms of the GNU Public 9 * License. 10 * %End-Header% 11 * 12 * ext2fs_get_pathname(fs, dir, ino, name) 13 * 14 * This function translates takes two inode numbers into a 15 * string, placing the result in <name>. <dir> is the containing 16 * directory inode, and <ino> is the inode number itself. If 17 * <ino> is zero, then ext2fs_get_pathname will return pathname 18 * of the the directory <dir>. 19 * 20 */ 21 22#include <stdio.h> 23#include <string.h> 24#if HAVE_UNISTD_H 25#include <unistd.h> 26#endif 27 28#include "ext2_fs.h" 29#include "ext2fs.h" 30 31struct get_pathname_struct { 32 ext2_ino_t search_ino; 33 ext2_ino_t parent; 34 char *name; 35 errcode_t errcode; 36}; 37 38#ifdef __TURBOC__ 39# pragma argsused 40#endif 41static int get_pathname_proc(struct ext2_dir_entry *dirent, 42 int offset EXT2FS_ATTR((unused)), 43 int blocksize EXT2FS_ATTR((unused)), 44 char *buf EXT2FS_ATTR((unused)), 45 void *priv_data) 46{ 47 struct get_pathname_struct *gp; 48 errcode_t retval; 49 50 gp = (struct get_pathname_struct *) priv_data; 51 52 if (((dirent->name_len & 0xFF) == 2) && 53 !strncmp(dirent->name, "..", 2)) 54 gp->parent = dirent->inode; 55 if (dirent->inode == gp->search_ino) { 56 retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1, 57 &gp->name); 58 if (retval) { 59 gp->errcode = retval; 60 return DIRENT_ABORT; 61 } 62 strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF)); 63 gp->name[dirent->name_len & 0xFF] = '\0'; 64 return DIRENT_ABORT; 65 } 66 return 0; 67} 68 69static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir, 70 ext2_ino_t ino, int maxdepth, 71 char *buf, char **name) 72{ 73 struct get_pathname_struct gp; 74 char *parent_name, *ret; 75 errcode_t retval; 76 77 if (dir == ino) { 78 retval = ext2fs_get_mem(2, name); 79 if (retval) 80 return retval; 81 strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : "."); 82 return 0; 83 } 84 85 if (!dir || (maxdepth < 0)) { 86 retval = ext2fs_get_mem(4, name); 87 if (retval) 88 return retval; 89 strcpy(*name, "..."); 90 return 0; 91 } 92 93 gp.search_ino = ino; 94 gp.parent = 0; 95 gp.name = 0; 96 gp.errcode = 0; 97 98 retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp); 99 if (retval) 100 goto cleanup; 101 if (gp.errcode) { 102 retval = gp.errcode; 103 goto cleanup; 104 } 105 106 retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1, 107 buf, &parent_name); 108 if (retval) 109 goto cleanup; 110 if (!ino) { 111 *name = parent_name; 112 return 0; 113 } 114 115 if (gp.name) 116 retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2, 117 &ret); 118 else 119 retval = ext2fs_get_mem(strlen(parent_name)+5, &ret); 120 if (retval) 121 goto cleanup; 122 123 ret[0] = 0; 124 if (parent_name[1]) 125 strcat(ret, parent_name); 126 strcat(ret, "/"); 127 if (gp.name) 128 strcat(ret, gp.name); 129 else 130 strcat(ret, "???"); 131 *name = ret; 132 ext2fs_free_mem(&parent_name); 133 retval = 0; 134 135cleanup: 136 ext2fs_free_mem(&gp.name); 137 return retval; 138} 139 140errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, 141 char **name) 142{ 143 char *buf; 144 errcode_t retval; 145 146 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 147 148 retval = ext2fs_get_mem(fs->blocksize, &buf); 149 if (retval) 150 return retval; 151 if (dir == ino) 152 ino = 0; 153 retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name); 154 ext2fs_free_mem(&buf); 155 return retval; 156 157} 158