~ubuntu-branches/ubuntu/edgy/e2fsprogs/edgy

« back to all changes in this revision

Viewing changes to lib/ext2fs/namei.c

  • Committer: Bazaar Package Importer
  • Author(s): Yann Dirson
  • Date: 2002-03-21 23:58:48 UTC
  • Revision ID: james.westby@ubuntu.com-20020321235848-cmmy98hy0nihp922
Tags: upstream-1.27
ImportĀ upstreamĀ versionĀ 1.27

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * namei.c --- ext2fs directory lookup operations
 
3
 * 
 
4
 * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
 
5
 *
 
6
 * %Begin-Header%
 
7
 * This file may be redistributed under the terms of the GNU Public
 
8
 * License.
 
9
 * %End-Header%
 
10
 */
 
11
 
 
12
#include <stdio.h>
 
13
#include <string.h>
 
14
#if HAVE_UNISTD_H
 
15
#include <unistd.h>
 
16
#endif
 
17
 
 
18
/* #define NAMEI_DEBUG */
 
19
 
 
20
#include "ext2_fs.h"
 
21
#include "ext2fs.h"
 
22
 
 
23
static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
 
24
                            const char *pathname, size_t pathlen, int follow,
 
25
                            int link_count, char *buf, ext2_ino_t *res_inode);
 
26
 
 
27
static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
 
28
                             ext2_ino_t inode, int link_count,
 
29
                             char *buf, ext2_ino_t *res_inode)
 
30
{
 
31
        char *pathname;
 
32
        char *buffer = 0;
 
33
        errcode_t retval;
 
34
        struct ext2_inode ei;
 
35
 
 
36
#ifdef NAMEI_DEBUG
 
37
        printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
 
38
               root, dir, inode, link_count);
 
39
        
 
40
#endif
 
41
        retval = ext2fs_read_inode (fs, inode, &ei);
 
42
        if (retval) return retval;
 
43
        if (!LINUX_S_ISLNK (ei.i_mode)) {
 
44
                *res_inode = inode;
 
45
                return 0;
 
46
        }
 
47
        if (link_count++ > 5) {
 
48
                return EXT2_ET_SYMLINK_LOOP;
 
49
        }
 
50
        if (ei.i_blocks) {
 
51
                retval = ext2fs_get_mem(fs->blocksize, (void **) &buffer);
 
52
                if (retval)
 
53
                        return retval;
 
54
                retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer);
 
55
                if (retval) {
 
56
                        ext2fs_free_mem((void **) &buffer);
 
57
                        return retval;
 
58
                }
 
59
                pathname = buffer;
 
60
        } else
 
61
                pathname = (char *)&(ei.i_block[0]);
 
62
        retval = open_namei(fs, root, dir, pathname, ei.i_size, 1,
 
63
                            link_count, buf, res_inode);
 
64
        if (buffer)
 
65
                ext2fs_free_mem((void **) &buffer);
 
66
        return retval;
 
67
}
 
68
 
 
69
/*
 
70
 * This routine interprets a pathname in the context of the current
 
71
 * directory and the root directory, and returns the inode of the
 
72
 * containing directory, and a pointer to the filename of the file
 
73
 * (pointing into the pathname) and the length of the filename.
 
74
 */
 
75
static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
 
76
                           const char *pathname, int pathlen,
 
77
                           int link_count, char *buf,
 
78
                           const char **name, int *namelen,
 
79
                           ext2_ino_t *res_inode)
 
80
{
 
81
        char c;
 
82
        const char *thisname;
 
83
        int len;
 
84
        ext2_ino_t inode;
 
85
        errcode_t retval;
 
86
 
 
87
        if ((c = *pathname) == '/') {
 
88
                dir = root;
 
89
                pathname++;
 
90
                pathlen--;
 
91
        }
 
92
        while (1) {
 
93
                thisname = pathname;
 
94
                for (len=0; --pathlen >= 0;len++) {
 
95
                        c = *(pathname++);
 
96
                        if (c == '/')
 
97
                                break;
 
98
                }
 
99
                if (pathlen < 0)
 
100
                        break;
 
101
                retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode);
 
102
                if (retval) return retval;
 
103
                retval = follow_link (fs, root, dir, inode,
 
104
                                      link_count, buf, &dir);
 
105
                if (retval) return retval;
 
106
        }
 
107
        *name = thisname;
 
108
        *namelen = len;
 
109
        *res_inode = dir;
 
110
        return 0;
 
111
}
 
112
 
 
113
static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
 
114
                            const char *pathname, size_t pathlen, int follow,
 
115
                            int link_count, char *buf, ext2_ino_t *res_inode)
 
116
{
 
117
        const char *basename;
 
118
        int namelen;
 
119
        ext2_ino_t dir, inode;
 
120
        errcode_t retval;
 
121
 
 
122
#ifdef NAMEI_DEBUG
 
123
        printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n",
 
124
               root, base, pathlen, pathname, link_count);
 
125
#endif
 
126
        retval = dir_namei(fs, root, base, pathname, pathlen,
 
127
                           link_count, buf, &basename, &namelen, &dir);
 
128
        if (retval) return retval;
 
129
        if (!namelen) {                     /* special case: '/usr/' etc */
 
130
                *res_inode=dir;
 
131
                return 0;
 
132
        }
 
133
        retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode);
 
134
        if (retval)
 
135
                return retval;
 
136
        if (follow) {
 
137
                retval = follow_link(fs, root, dir, inode, link_count,
 
138
                                     buf, &inode);
 
139
                if (retval)
 
140
                        return retval;
 
141
        }
 
142
#ifdef NAMEI_DEBUG
 
143
        printf("open_namei: (link_count=%d) returns %lu\n",
 
144
               link_count, inode);
 
145
#endif
 
146
        *res_inode = inode;
 
147
        return 0;
 
148
}
 
149
 
 
150
errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
 
151
                       const char *name, ext2_ino_t *inode)
 
152
{
 
153
        char *buf;
 
154
        errcode_t retval;
 
155
        
 
156
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
157
 
 
158
        retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
 
159
        if (retval)
 
160
                return retval;
 
161
        
 
162
        retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0,
 
163
                            buf, inode);
 
164
 
 
165
        ext2fs_free_mem((void **) &buf);
 
166
        return retval;
 
167
}
 
168
 
 
169
errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
 
170
                              const char *name, ext2_ino_t *inode)
 
171
{
 
172
        char *buf;
 
173
        errcode_t retval;
 
174
        
 
175
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
176
 
 
177
        retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
 
178
        if (retval)
 
179
                return retval;
 
180
        
 
181
        retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0,
 
182
                            buf, inode);
 
183
 
 
184
        ext2fs_free_mem((void **) &buf);
 
185
        return retval;
 
186
}
 
187
 
 
188
errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
 
189
                        ext2_ino_t inode, ext2_ino_t *res_inode)
 
190
{
 
191
        char *buf;
 
192
        errcode_t retval;
 
193
        
 
194
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
195
 
 
196
        retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
 
197
        if (retval)
 
198
                return retval;
 
199
 
 
200
        retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
 
201
 
 
202
        ext2fs_free_mem((void **) &buf);
 
203
        return retval;
 
204
}
 
205