OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [stat.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/fs/stat.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
#include <linux/config.h>
8
#include <linux/mm.h>
9
#include <linux/errno.h>
10
#include <linux/file.h>
11
#include <linux/smp_lock.h>
12
#include <linux/highuid.h>
13
 
14
#include <asm/uaccess.h>
15
 
16
/*
17
 * Revalidate the inode. This is required for proper NFS attribute caching.
18
 */
19
static __inline__ int
20
do_revalidate(struct dentry *dentry)
21
{
22
        struct inode * inode = dentry->d_inode;
23
        if (inode->i_op && inode->i_op->revalidate)
24
                return inode->i_op->revalidate(dentry);
25
        return 0;
26
}
27
 
28
 
29
#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
30
 
31
/*
32
 * For backward compatibility?  Maybe this should be moved
33
 * into arch/i386 instead?
34
 */
35
static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
36
{
37
        static int warncount = 5;
38
        struct __old_kernel_stat tmp;
39
 
40
        memset(&tmp, 0, sizeof(struct __old_kernel_stat));
41
 
42
        if (warncount > 0) {
43
                warncount--;
44
                printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
45
                        current->comm);
46
        } else if (warncount < 0) {
47
                /* it's laughable, but... */
48
                warncount = 0;
49
        }
50
 
51
        tmp.st_dev = kdev_t_to_nr(inode->i_dev);
52
        tmp.st_ino = inode->i_ino;
53
        tmp.st_mode = inode->i_mode;
54
        tmp.st_nlink = inode->i_nlink;
55
        SET_OLDSTAT_UID(tmp, inode->i_uid);
56
        SET_OLDSTAT_GID(tmp, inode->i_gid);
57
        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
58
#if BITS_PER_LONG == 32
59
        if (inode->i_size > MAX_NON_LFS)
60
                return -EOVERFLOW;
61
#endif  
62
        tmp.st_size = inode->i_size;
63
        tmp.st_atime = inode->i_atime;
64
        tmp.st_mtime = inode->i_mtime;
65
        tmp.st_ctime = inode->i_ctime;
66
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
67
}
68
 
69
#endif
70
 
71
static int cp_new_stat(struct inode * inode, struct stat * statbuf)
72
{
73
        struct stat tmp;
74
        unsigned int blocks, indirect;
75
 
76
        memset(&tmp, 0, sizeof(tmp));
77
        tmp.st_dev = kdev_t_to_nr(inode->i_dev);
78
        tmp.st_ino = inode->i_ino;
79
        tmp.st_mode = inode->i_mode;
80
        tmp.st_nlink = inode->i_nlink;
81
        SET_STAT_UID(tmp, inode->i_uid);
82
        SET_STAT_GID(tmp, inode->i_gid);
83
        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
84
#if BITS_PER_LONG == 32
85
        if (inode->i_size > MAX_NON_LFS)
86
                return -EOVERFLOW;
87
#endif  
88
        tmp.st_size = inode->i_size;
89
        tmp.st_atime = inode->i_atime;
90
        tmp.st_mtime = inode->i_mtime;
91
        tmp.st_ctime = inode->i_ctime;
92
/*
93
 * st_blocks and st_blksize are approximated with a simple algorithm if
94
 * they aren't supported directly by the filesystem. The minix and msdos
95
 * filesystems don't keep track of blocks, so they would either have to
96
 * be counted explicitly (by delving into the file itself), or by using
97
 * this simple algorithm to get a reasonable (although not 100% accurate)
98
 * value.
99
 */
100
 
101
/*
102
 * Use minix fs values for the number of direct and indirect blocks.  The
103
 * count is now exact for the minix fs except that it counts zero blocks.
104
 * Everything is in units of BLOCK_SIZE until the assignment to
105
 * tmp.st_blksize.
106
 */
107
#define D_B   7
108
#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
109
 
110
        if (!inode->i_blksize) {
111
                blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
112
                if (blocks > D_B) {
113
                        indirect = (blocks - D_B + I_B - 1) / I_B;
114
                        blocks += indirect;
115
                        if (indirect > 1) {
116
                                indirect = (indirect - 1 + I_B - 1) / I_B;
117
                                blocks += indirect;
118
                                if (indirect > 1)
119
                                        blocks++;
120
                        }
121
                }
122
                tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
123
                tmp.st_blksize = BLOCK_SIZE;
124
        } else {
125
                tmp.st_blocks = inode->i_blocks;
126
                tmp.st_blksize = inode->i_blksize;
127
        }
128
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
129
}
130
 
131
 
132
#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
133
/*
134
 * For backward compatibility?  Maybe this should be moved
135
 * into arch/i386 instead?
136
 */
137
asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
138
{
139
        struct nameidata nd;
140
        int error;
141
 
142
        error = user_path_walk(filename, &nd);
143
        if (!error) {
144
                error = do_revalidate(nd.dentry);
145
                if (!error)
146
                        error = cp_old_stat(nd.dentry->d_inode, statbuf);
147
                path_release(&nd);
148
        }
149
        return error;
150
}
151
#endif
152
 
153
asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
154
{
155
        struct nameidata nd;
156
        int error;
157
 
158
        error = user_path_walk(filename, &nd);
159
        if (!error) {
160
                error = do_revalidate(nd.dentry);
161
                if (!error)
162
                        error = cp_new_stat(nd.dentry->d_inode, statbuf);
163
                path_release(&nd);
164
        }
165
        return error;
166
}
167
 
168
#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
169
 
170
/*
171
 * For backward compatibility?  Maybe this should be moved
172
 * into arch/i386 instead?
173
 */
174
asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
175
{
176
        struct nameidata nd;
177
        int error;
178
 
179
        error = user_path_walk_link(filename, &nd);
180
        if (!error) {
181
                error = do_revalidate(nd.dentry);
182
                if (!error)
183
                        error = cp_old_stat(nd.dentry->d_inode, statbuf);
184
                path_release(&nd);
185
        }
186
        return error;
187
}
188
 
189
#endif
190
 
191
asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
192
{
193
        struct nameidata nd;
194
        int error;
195
 
196
        error = user_path_walk_link(filename, &nd);
197
        if (!error) {
198
                error = do_revalidate(nd.dentry);
199
                if (!error)
200
                        error = cp_new_stat(nd.dentry->d_inode, statbuf);
201
                path_release(&nd);
202
        }
203
        return error;
204
}
205
 
206
#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
207
 
208
/*
209
 * For backward compatibility?  Maybe this should be moved
210
 * into arch/i386 instead?
211
 */
212
asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
213
{
214
        struct file * f;
215
        int err = -EBADF;
216
 
217
        f = fget(fd);
218
        if (f) {
219
                struct dentry * dentry = f->f_dentry;
220
 
221
                err = do_revalidate(dentry);
222
                if (!err)
223
                        err = cp_old_stat(dentry->d_inode, statbuf);
224
                fput(f);
225
        }
226
        return err;
227
}
228
 
229
#endif
230
 
231
asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf)
232
{
233
        struct file * f;
234
        int err = -EBADF;
235
 
236
        f = fget(fd);
237
        if (f) {
238
                struct dentry * dentry = f->f_dentry;
239
 
240
                err = do_revalidate(dentry);
241
                if (!err)
242
                        err = cp_new_stat(dentry->d_inode, statbuf);
243
                fput(f);
244
        }
245
        return err;
246
}
247
 
248
asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz)
249
{
250
        struct nameidata nd;
251
        int error;
252
 
253
        if (bufsiz <= 0)
254
                return -EINVAL;
255
 
256
        error = user_path_walk_link(path, &nd);
257
        if (!error) {
258
                struct inode * inode = nd.dentry->d_inode;
259
 
260
                error = -EINVAL;
261
                if (inode->i_op && inode->i_op->readlink &&
262
                    !(error = do_revalidate(nd.dentry))) {
263
                        UPDATE_ATIME(inode);
264
                        error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
265
                }
266
                path_release(&nd);
267
        }
268
        return error;
269
}
270
 
271
 
272
/* ---------- LFS-64 ----------- */
273
#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips64) && !defined(__x86_64__) && !defined(CONFIG_ARCH_S390X)
274
 
275
static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
276
{
277
        struct stat64 tmp;
278
        unsigned int blocks, indirect;
279
 
280
        memset(&tmp, 0, sizeof(tmp));
281
        tmp.st_dev = kdev_t_to_nr(inode->i_dev);
282
        tmp.st_ino = inode->i_ino;
283
#ifdef STAT64_HAS_BROKEN_ST_INO
284
        tmp.__st_ino = inode->i_ino;
285
#endif
286
        tmp.st_mode = inode->i_mode;
287
        tmp.st_nlink = inode->i_nlink;
288
        tmp.st_uid = inode->i_uid;
289
        tmp.st_gid = inode->i_gid;
290
        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
291
        tmp.st_atime = inode->i_atime;
292
        tmp.st_mtime = inode->i_mtime;
293
        tmp.st_ctime = inode->i_ctime;
294
        tmp.st_size = inode->i_size;
295
/*
296
 * st_blocks and st_blksize are approximated with a simple algorithm if
297
 * they aren't supported directly by the filesystem. The minix and msdos
298
 * filesystems don't keep track of blocks, so they would either have to
299
 * be counted explicitly (by delving into the file itself), or by using
300
 * this simple algorithm to get a reasonable (although not 100% accurate)
301
 * value.
302
 */
303
 
304
/*
305
 * Use minix fs values for the number of direct and indirect blocks.  The
306
 * count is now exact for the minix fs except that it counts zero blocks.
307
 * Everything is in units of BLOCK_SIZE until the assignment to
308
 * tmp.st_blksize.
309
 */
310
#define D_B   7
311
#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
312
 
313
        if (!inode->i_blksize) {
314
                blocks = (tmp.st_size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
315
                if (blocks > D_B) {
316
                        indirect = (blocks - D_B + I_B - 1) / I_B;
317
                        blocks += indirect;
318
                        if (indirect > 1) {
319
                                indirect = (indirect - 1 + I_B - 1) / I_B;
320
                                blocks += indirect;
321
                                if (indirect > 1)
322
                                        blocks++;
323
                        }
324
                }
325
                tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
326
                tmp.st_blksize = BLOCK_SIZE;
327
        } else {
328
                tmp.st_blocks = inode->i_blocks;
329
                tmp.st_blksize = inode->i_blksize;
330
        }
331
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
332
}
333
 
334
asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags)
335
{
336
        struct nameidata nd;
337
        int error;
338
 
339
        error = user_path_walk(filename, &nd);
340
        if (!error) {
341
                error = do_revalidate(nd.dentry);
342
                if (!error)
343
                        error = cp_new_stat64(nd.dentry->d_inode, statbuf);
344
                path_release(&nd);
345
        }
346
        return error;
347
}
348
 
349
asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags)
350
{
351
        struct nameidata nd;
352
        int error;
353
 
354
        error = user_path_walk_link(filename, &nd);
355
        if (!error) {
356
                error = do_revalidate(nd.dentry);
357
                if (!error)
358
                        error = cp_new_stat64(nd.dentry->d_inode, statbuf);
359
                path_release(&nd);
360
        }
361
        return error;
362
}
363
 
364
asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags)
365
{
366
        struct file * f;
367
        int err = -EBADF;
368
 
369
        f = fget(fd);
370
        if (f) {
371
                struct dentry * dentry = f->f_dentry;
372
 
373
                err = do_revalidate(dentry);
374
                if (!err)
375
                        err = cp_new_stat64(dentry->d_inode, statbuf);
376
                fput(f);
377
        }
378
        return err;
379
}
380
 
381
#endif /* LFS-64 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.