stat.c 11.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6
/*
 *  linux/fs/stat.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

7
#include <linux/export.h>
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/highuid.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/security.h>
#include <linux/syscalls.h>
16
#include <linux/pagemap.h>
L
Linus Torvalds 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29

#include <asm/uaccess.h>
#include <asm/unistd.h>

void generic_fillattr(struct inode *inode, struct kstat *stat)
{
	stat->dev = inode->i_sb->s_dev;
	stat->ino = inode->i_ino;
	stat->mode = inode->i_mode;
	stat->nlink = inode->i_nlink;
	stat->uid = inode->i_uid;
	stat->gid = inode->i_gid;
	stat->rdev = inode->i_rdev;
30
	stat->size = i_size_read(inode);
L
Linus Torvalds 已提交
31 32 33
	stat->atime = inode->i_atime;
	stat->mtime = inode->i_mtime;
	stat->ctime = inode->i_ctime;
34
	stat->blksize = (1 << inode->i_blkbits);
35
	stat->blocks = inode->i_blocks;
L
Linus Torvalds 已提交
36 37 38 39
}

EXPORT_SYMBOL(generic_fillattr);

A
Al Viro 已提交
40
int vfs_getattr(struct path *path, struct kstat *stat)
L
Linus Torvalds 已提交
41
{
A
Al Viro 已提交
42
	struct inode *inode = path->dentry->d_inode;
L
Linus Torvalds 已提交
43 44
	int retval;

A
Al Viro 已提交
45
	retval = security_inode_getattr(path->mnt, path->dentry);
L
Linus Torvalds 已提交
46 47 48 49
	if (retval)
		return retval;

	if (inode->i_op->getattr)
A
Al Viro 已提交
50
		return inode->i_op->getattr(path->mnt, path->dentry, stat);
L
Linus Torvalds 已提交
51 52 53 54 55 56 57 58 59

	generic_fillattr(inode, stat);
	return 0;
}

EXPORT_SYMBOL(vfs_getattr);

int vfs_fstat(unsigned int fd, struct kstat *stat)
{
60
	struct fd f = fdget_raw(fd);
L
Linus Torvalds 已提交
61 62
	int error = -EBADF;

63
	if (f.file) {
A
Al Viro 已提交
64
		error = vfs_getattr(&f.file->f_path, stat);
65
		fdput(f);
L
Linus Torvalds 已提交
66 67 68 69 70
	}
	return error;
}
EXPORT_SYMBOL(vfs_fstat);

71 72
int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
		int flag)
73
{
74
	struct path path;
75
	int error = -EINVAL;
76
	unsigned int lookup_flags = 0;
77

78 79
	if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
		      AT_EMPTY_PATH)) != 0)
80 81
		goto out;

82 83
	if (!(flag & AT_SYMLINK_NOFOLLOW))
		lookup_flags |= LOOKUP_FOLLOW;
84 85
	if (flag & AT_EMPTY_PATH)
		lookup_flags |= LOOKUP_EMPTY;
86
retry:
87 88 89 90
	error = user_path_at(dfd, filename, lookup_flags, &path);
	if (error)
		goto out;

A
Al Viro 已提交
91
	error = vfs_getattr(&path, stat);
92
	path_put(&path);
93 94 95 96
	if (retry_estale(error, lookup_flags)) {
		lookup_flags |= LOOKUP_REVAL;
		goto retry;
	}
97 98 99 100 101
out:
	return error;
}
EXPORT_SYMBOL(vfs_fstatat);

102
int vfs_stat(const char __user *name, struct kstat *stat)
103 104 105 106 107
{
	return vfs_fstatat(AT_FDCWD, name, stat, 0);
}
EXPORT_SYMBOL(vfs_stat);

108
int vfs_lstat(const char __user *name, struct kstat *stat)
109 110 111 112 113
{
	return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW);
}
EXPORT_SYMBOL(vfs_lstat);

114

L
Linus Torvalds 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
#ifdef __ARCH_WANT_OLD_STAT

/*
 * For backward compatibility?  Maybe this should be moved
 * into arch/i386 instead?
 */
static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
{
	static int warncount = 5;
	struct __old_kernel_stat tmp;
	
	if (warncount > 0) {
		warncount--;
		printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
			current->comm);
	} else if (warncount < 0) {
		/* it's laughable, but... */
		warncount = 0;
	}

	memset(&tmp, 0, sizeof(struct __old_kernel_stat));
	tmp.st_dev = old_encode_dev(stat->dev);
	tmp.st_ino = stat->ino;
138 139
	if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
		return -EOVERFLOW;
L
Linus Torvalds 已提交
140 141 142 143
	tmp.st_mode = stat->mode;
	tmp.st_nlink = stat->nlink;
	if (tmp.st_nlink != stat->nlink)
		return -EOVERFLOW;
144 145
	SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
	SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
L
Linus Torvalds 已提交
146 147 148 149 150 151 152 153 154 155 156 157
	tmp.st_rdev = old_encode_dev(stat->rdev);
#if BITS_PER_LONG == 32
	if (stat->size > MAX_NON_LFS)
		return -EOVERFLOW;
#endif	
	tmp.st_size = stat->size;
	tmp.st_atime = stat->atime.tv_sec;
	tmp.st_mtime = stat->mtime.tv_sec;
	tmp.st_ctime = stat->ctime.tv_sec;
	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

158 159
SYSCALL_DEFINE2(stat, const char __user *, filename,
		struct __old_kernel_stat __user *, statbuf)
L
Linus Torvalds 已提交
160 161
{
	struct kstat stat;
162
	int error;
L
Linus Torvalds 已提交
163

164 165 166
	error = vfs_stat(filename, &stat);
	if (error)
		return error;
L
Linus Torvalds 已提交
167

168
	return cp_old_stat(&stat, statbuf);
L
Linus Torvalds 已提交
169
}
170

171 172
SYSCALL_DEFINE2(lstat, const char __user *, filename,
		struct __old_kernel_stat __user *, statbuf)
L
Linus Torvalds 已提交
173 174
{
	struct kstat stat;
175
	int error;
L
Linus Torvalds 已提交
176

177 178 179
	error = vfs_lstat(filename, &stat);
	if (error)
		return error;
L
Linus Torvalds 已提交
180

181
	return cp_old_stat(&stat, statbuf);
L
Linus Torvalds 已提交
182
}
183 184

SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf)
L
Linus Torvalds 已提交
185 186 187 188 189 190 191 192 193 194 195 196
{
	struct kstat stat;
	int error = vfs_fstat(fd, &stat);

	if (!error)
		error = cp_old_stat(&stat, statbuf);

	return error;
}

#endif /* __ARCH_WANT_OLD_STAT */

197 198 199 200 201 202 203 204 205
#if BITS_PER_LONG == 32
#  define choose_32_64(a,b) a
#else
#  define choose_32_64(a,b) b
#endif

#define valid_dev(x)  choose_32_64(old_valid_dev,new_valid_dev)(x)
#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)

206 207 208 209
#ifndef INIT_STRUCT_STAT_PADDING
#  define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
#endif

L
Linus Torvalds 已提交
210 211 212 213
static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
{
	struct stat tmp;

214
	if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
L
Linus Torvalds 已提交
215
		return -EOVERFLOW;
216 217
#if BITS_PER_LONG == 32
	if (stat->size > MAX_NON_LFS)
L
Linus Torvalds 已提交
218 219 220
		return -EOVERFLOW;
#endif

221
	INIT_STRUCT_STAT_PADDING(tmp);
222
	tmp.st_dev = encode_dev(stat->dev);
L
Linus Torvalds 已提交
223
	tmp.st_ino = stat->ino;
224 225
	if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
		return -EOVERFLOW;
L
Linus Torvalds 已提交
226 227 228 229
	tmp.st_mode = stat->mode;
	tmp.st_nlink = stat->nlink;
	if (tmp.st_nlink != stat->nlink)
		return -EOVERFLOW;
230 231
	SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
	SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
232
	tmp.st_rdev = encode_dev(stat->rdev);
L
Linus Torvalds 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246
	tmp.st_size = stat->size;
	tmp.st_atime = stat->atime.tv_sec;
	tmp.st_mtime = stat->mtime.tv_sec;
	tmp.st_ctime = stat->ctime.tv_sec;
#ifdef STAT_HAVE_NSEC
	tmp.st_atime_nsec = stat->atime.tv_nsec;
	tmp.st_mtime_nsec = stat->mtime.tv_nsec;
	tmp.st_ctime_nsec = stat->ctime.tv_nsec;
#endif
	tmp.st_blocks = stat->blocks;
	tmp.st_blksize = stat->blksize;
	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

247 248
SYSCALL_DEFINE2(newstat, const char __user *, filename,
		struct stat __user *, statbuf)
249 250
{
	struct kstat stat;
251
	int error = vfs_stat(filename, &stat);
252

253 254 255
	if (error)
		return error;
	return cp_new_stat(&stat, statbuf);
256 257
}

258 259
SYSCALL_DEFINE2(newlstat, const char __user *, filename,
		struct stat __user *, statbuf)
L
Linus Torvalds 已提交
260 261
{
	struct kstat stat;
262
	int error;
L
Linus Torvalds 已提交
263

264 265 266
	error = vfs_lstat(filename, &stat);
	if (error)
		return error;
L
Linus Torvalds 已提交
267

268
	return cp_new_stat(&stat, statbuf);
L
Linus Torvalds 已提交
269
}
270

271
#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
272
SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
273
		struct stat __user *, statbuf, int, flag)
L
Linus Torvalds 已提交
274 275
{
	struct kstat stat;
276
	int error;
L
Linus Torvalds 已提交
277

278 279 280 281
	error = vfs_fstatat(dfd, filename, &stat, flag);
	if (error)
		return error;
	return cp_new_stat(&stat, statbuf);
L
Linus Torvalds 已提交
282
}
U
Ulrich Drepper 已提交
283
#endif
284

285
SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
L
Linus Torvalds 已提交
286 287 288 289 290 291 292 293 294 295
{
	struct kstat stat;
	int error = vfs_fstat(fd, &stat);

	if (!error)
		error = cp_new_stat(&stat, statbuf);

	return error;
}

296 297
SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
		char __user *, buf, int, bufsiz)
L
Linus Torvalds 已提交
298
{
299
	struct path path;
L
Linus Torvalds 已提交
300
	int error;
301
	int empty = 0;
302
	unsigned int lookup_flags = LOOKUP_EMPTY;
L
Linus Torvalds 已提交
303 304 305 306

	if (bufsiz <= 0)
		return -EINVAL;

307 308
retry:
	error = user_path_at_empty(dfd, pathname, lookup_flags, &path, &empty);
L
Linus Torvalds 已提交
309
	if (!error) {
310
		struct inode *inode = path.dentry->d_inode;
L
Linus Torvalds 已提交
311

312
		error = empty ? -ENOENT : -EINVAL;
A
Al Viro 已提交
313
		if (inode->i_op->readlink) {
314
			error = security_inode_readlink(path.dentry);
L
Linus Torvalds 已提交
315
			if (!error) {
A
Al Viro 已提交
316
				touch_atime(&path);
317
				error = inode->i_op->readlink(path.dentry,
318
							      buf, bufsiz);
L
Linus Torvalds 已提交
319 320
			}
		}
321
		path_put(&path);
322 323 324 325
		if (retry_estale(error, lookup_flags)) {
			lookup_flags |= LOOKUP_REVAL;
			goto retry;
		}
L
Linus Torvalds 已提交
326 327 328 329
	}
	return error;
}

330 331
SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf,
		int, bufsiz)
332 333 334 335
{
	return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
}

L
Linus Torvalds 已提交
336 337

/* ---------- LFS-64 ----------- */
338
#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
L
Linus Torvalds 已提交
339

340 341 342 343
#ifndef INIT_STRUCT_STAT64_PADDING
#  define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st))
#endif

L
Linus Torvalds 已提交
344 345 346 347
static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
{
	struct stat64 tmp;

348
	INIT_STRUCT_STAT64_PADDING(tmp);
L
Linus Torvalds 已提交
349 350 351 352 353 354 355 356 357 358 359
#ifdef CONFIG_MIPS
	/* mips has weird padding, so we don't get 64 bits there */
	if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
		return -EOVERFLOW;
	tmp.st_dev = new_encode_dev(stat->dev);
	tmp.st_rdev = new_encode_dev(stat->rdev);
#else
	tmp.st_dev = huge_encode_dev(stat->dev);
	tmp.st_rdev = huge_encode_dev(stat->rdev);
#endif
	tmp.st_ino = stat->ino;
360 361
	if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
		return -EOVERFLOW;
L
Linus Torvalds 已提交
362 363 364 365 366
#ifdef STAT64_HAS_BROKEN_ST_INO
	tmp.__st_ino = stat->ino;
#endif
	tmp.st_mode = stat->mode;
	tmp.st_nlink = stat->nlink;
367 368
	tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
	tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
L
Linus Torvalds 已提交
369 370 371 372 373 374 375 376 377 378 379 380
	tmp.st_atime = stat->atime.tv_sec;
	tmp.st_atime_nsec = stat->atime.tv_nsec;
	tmp.st_mtime = stat->mtime.tv_sec;
	tmp.st_mtime_nsec = stat->mtime.tv_nsec;
	tmp.st_ctime = stat->ctime.tv_sec;
	tmp.st_ctime_nsec = stat->ctime.tv_nsec;
	tmp.st_size = stat->size;
	tmp.st_blocks = stat->blocks;
	tmp.st_blksize = stat->blksize;
	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

381 382
SYSCALL_DEFINE2(stat64, const char __user *, filename,
		struct stat64 __user *, statbuf)
L
Linus Torvalds 已提交
383 384 385 386 387 388 389 390 391
{
	struct kstat stat;
	int error = vfs_stat(filename, &stat);

	if (!error)
		error = cp_new_stat64(&stat, statbuf);

	return error;
}
392

393 394
SYSCALL_DEFINE2(lstat64, const char __user *, filename,
		struct stat64 __user *, statbuf)
L
Linus Torvalds 已提交
395 396 397 398 399 400 401 402 403
{
	struct kstat stat;
	int error = vfs_lstat(filename, &stat);

	if (!error)
		error = cp_new_stat64(&stat, statbuf);

	return error;
}
404 405

SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
L
Linus Torvalds 已提交
406 407 408 409 410 411 412 413 414 415
{
	struct kstat stat;
	int error = vfs_fstat(fd, &stat);

	if (!error)
		error = cp_new_stat64(&stat, statbuf);

	return error;
}

416
SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
417
		struct stat64 __user *, statbuf, int, flag)
U
Ulrich Drepper 已提交
418 419
{
	struct kstat stat;
420
	int error;
U
Ulrich Drepper 已提交
421

422 423 424 425
	error = vfs_fstatat(dfd, filename, &stat, flag);
	if (error)
		return error;
	return cp_new_stat64(&stat, statbuf);
U
Ulrich Drepper 已提交
426
}
427
#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
L
Linus Torvalds 已提交
428

429 430
/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
void __inode_add_bytes(struct inode *inode, loff_t bytes)
L
Linus Torvalds 已提交
431 432 433 434 435 436 437 438
{
	inode->i_blocks += bytes >> 9;
	bytes &= 511;
	inode->i_bytes += bytes;
	if (inode->i_bytes >= 512) {
		inode->i_blocks++;
		inode->i_bytes -= 512;
	}
439 440 441 442 443 444
}

void inode_add_bytes(struct inode *inode, loff_t bytes)
{
	spin_lock(&inode->i_lock);
	__inode_add_bytes(inode, bytes);
L
Linus Torvalds 已提交
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
	spin_unlock(&inode->i_lock);
}

EXPORT_SYMBOL(inode_add_bytes);

void inode_sub_bytes(struct inode *inode, loff_t bytes)
{
	spin_lock(&inode->i_lock);
	inode->i_blocks -= bytes >> 9;
	bytes &= 511;
	if (inode->i_bytes < bytes) {
		inode->i_blocks--;
		inode->i_bytes += 512;
	}
	inode->i_bytes -= bytes;
	spin_unlock(&inode->i_lock);
}

EXPORT_SYMBOL(inode_sub_bytes);

loff_t inode_get_bytes(struct inode *inode)
{
	loff_t ret;

	spin_lock(&inode->i_lock);
	ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
	spin_unlock(&inode->i_lock);
	return ret;
}

EXPORT_SYMBOL(inode_get_bytes);

void inode_set_bytes(struct inode *inode, loff_t bytes)
{
	/* Caller is here responsible for sufficient locking
	 * (ie. inode->i_lock) */
	inode->i_blocks = bytes >> 9;
	inode->i_bytes = bytes & 511;
}

EXPORT_SYMBOL(inode_set_bytes);