📄 stat.c
字号:
/* stat.c -- display file or filesystem status
Copyright (C) 2001, 2002 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
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 02111-1307, USA.
Written by Michael Meskes. */
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SYSMACROS_H
# include <sys/sysmacros.h>
#endif
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <time.h>
#if HAVE_SYS_STATVFS_H
# include <sys/statvfs.h>
#endif
#if HAVE_SYS_VFS_H
# include <sys/vfs.h>
#endif
/* NetBSD 1.5.2 needs these, for the declaration of struct statfs. */
#if !HAVE_SYS_STATVFS_H && !HAVE_SYS_VFS_H
# if HAVE_SYS_MOUNT_H && HAVE_SYS_PARAM_H
# include <sys/param.h>
# include <sys/mount.h>
# endif
#endif
#include <string.h>
#include <ctype.h>
#include "system.h"
#include "closeout.h"
#include "error.h"
#include "filemode.h"
#include "fs.h"
#include "getopt.h"
#include "quote.h"
#include "quotearg.h"
#include "xreadlink.h"
#define NAMEMAX_FORMAT PRIuMAX
#if HAVE_STRUCT_STATVFS_F_BASETYPE
# define STRUCT_STATVFS struct statvfs
# define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATVFS
# if HAVE_STRUCT_STATVFS_F_NAMEMAX
# define SB_F_NAMEMAX(S) ((uintmax_t) ((S)->f_namemax))
# endif
#else
# define STRUCT_STATVFS struct statfs
# define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATFS
# if HAVE_STRUCT_STATFS_F_NAMELEN
# define SB_F_NAMEMAX(S) ((uintmax_t) ((S)->f_namelen))
# endif
#endif
#ifndef SB_F_NAMEMAX
/* NetBSD 1.5.2 has neither f_namemax nor f_namelen. */
# define SB_F_NAMEMAX(S) "*"
# undef NAMEMAX_FORMAT
# define NAMEMAX_FORMAT "s"
#endif
size_t nstrftime PARAMS ((char *, size_t, char const *,
struct tm const *, int, int));
#define PROGRAM_NAME "stat"
#define AUTHORS "Michael Meskes"
static struct option const long_options[] = {
{"link", no_argument, 0, 'l'}, /* deprecated. FIXME: remove in 2003 */
{"dereference", no_argument, 0, 'L'},
{"format", required_argument, 0, 'c'},
{"filesystem", no_argument, 0, 'f'},
{"terse", no_argument, 0, 't'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
char *program_name;
static void
print_human_type (mode_t mode)
{
char const *type;
switch (mode & S_IFMT)
{
case S_IFDIR:
type = "Directory";
break;
case S_IFCHR:
type = "Character Device";
break;
case S_IFBLK:
type = "Block Device";
break;
case S_IFREG:
type = "Regular File";
break;
case S_IFLNK:
type = "Symbolic Link";
break;
case S_IFSOCK:
type = "Socket";
break;
case S_IFIFO:
type = "Fifo File";
break;
default:
type = "Unknown";
}
fputs (type, stdout);
}
/* Return the type of the specified file system.
Some systems have statfvs.f_basetype[FSTYPSZ]. (AIX, HP-UX, and Solaris)
Others have statfs.f_fstypename[MFSNAMELEN]. (NetBSD 1.5.2)
Still others have neither and have to get by with f_type (Linux). */
static char *
human_fstype (STRUCT_STATVFS const *statfsbuf)
{
#if HAVE_STRUCT_STATVFS_F_BASETYPE
return statfsbuf->f_basetype;
#else
# if HAVE_STRUCT_STATFS_F_FSTYPENAME
return statfsbuf->f_fstypename;
# else
char const *type;
switch (statfsbuf->f_type)
{
# if defined __linux__
case S_MAGIC_AFFS:
type = "affs";
break;
case S_MAGIC_EXT:
type = "ext";
break;
case S_MAGIC_EXT2_OLD:
type = "ext2";
break;
case S_MAGIC_EXT2:
type = "ext2/ext3";
break;
case S_MAGIC_HPFS:
type = "hpfs";
break;
case S_MAGIC_ISOFS:
type = "isofs";
break;
case S_MAGIC_ISOFS_WIN:
type = "isofs";
break;
case S_MAGIC_ISOFS_R_WIN:
type = "isofs";
break;
case S_MAGIC_MINIX:
type = "minix";
break;
case S_MAGIC_MINIX_30:
type = "minix (30 char.)";
break;
case S_MAGIC_MINIX_V2:
type = "minix v2";
break;
case S_MAGIC_MINIX_V2_30:
type = "minix v2 (30 char.)";
break;
case S_MAGIC_MSDOS:
type = "msdos";
break;
case S_MAGIC_FAT:
type = "fat";
break;
case S_MAGIC_NCP:
type = "novell";
break;
case S_MAGIC_NFS:
type = "nfs";
break;
case S_MAGIC_PROC:
type = "proc";
break;
case S_MAGIC_SMB:
type = "smb";
break;
case S_MAGIC_XENIX:
type = "xenix";
break;
case S_MAGIC_SYSV4:
type = "sysv4";
break;
case S_MAGIC_SYSV2:
type = "sysv2";
break;
case S_MAGIC_COH:
type = "coh";
break;
case S_MAGIC_UFS:
type = "ufs";
break;
case S_MAGIC_XIAFS:
type = "xia";
break;
case S_MAGIC_NTFS:
type = "ntfs";
break;
case S_MAGIC_TMPFS:
type = "tmpfs";
break;
case S_MAGIC_REISERFS:
type = "reiserfs";
break;
case S_MAGIC_CRAMFS:
type = "cramfs";
break;
case S_MAGIC_ROMFS:
type = "romfs";
break;
# elif __GNU__
case FSTYPE_UFS:
type = "ufs";
break;
case FSTYPE_NFS:
type = "nfs";
break;
case FSTYPE_GFS:
type = "gfs";
break;
case FSTYPE_LFS:
type = "lfs";
break;
case FSTYPE_SYSV:
type = "sysv";
break;
case FSTYPE_FTP:
type = "ftp";
break;
case FSTYPE_TAR:
type = "tar";
break;
case FSTYPE_AR:
type = "ar";
break;
case FSTYPE_CPIO:
type = "cpio";
break;
case FSTYPE_MSLOSS:
type = "msloss";
break;
case FSTYPE_CPM:
type = "cpm";
break;
case FSTYPE_HFS:
type = "hfs";
break;
case FSTYPE_DTFS:
type = "dtfs";
break;
case FSTYPE_GRFS:
type = "grfs";
break;
case FSTYPE_TERM:
type = "term";
break;
case FSTYPE_DEV:
type = "dev";
break;
case FSTYPE_PROC:
type = "proc";
break;
case FSTYPE_IFSOCK:
type = "ifsock";
break;
case FSTYPE_AFS:
type = "afs";
break;
case FSTYPE_DFS:
type = "dfs";
break;
case FSTYPE_PROC9:
type = "proc9";
break;
case FSTYPE_SOCKET:
type = "socket";
break;
case FSTYPE_MISC:
type = "misc";
break;
case FSTYPE_EXT2FS:
type = "ext2/ext3";
break;
case FSTYPE_HTTP:
type = "http";
break;
case FSTYPE_MEMFS:
type = "memfs";
break;
case FSTYPE_ISO9660:
type = "iso9660";
break;
# endif
default:
type = NULL;
break;
}
if (type)
return (char *) type;
{
static char buf[sizeof "UNKNOWN (0x%x)" - 2
+ 2 * sizeof (statfsbuf->f_type)];
sprintf (buf, "UNKNOWN (0x%x)", statfsbuf->f_type);
return buf;
}
# endif
#endif
}
static void
print_human_access (struct stat const *statbuf)
{
char modebuf[11];
mode_string (statbuf->st_mode, modebuf);
modebuf[10] = 0;
fputs (modebuf, stdout);
}
static void
print_human_time (time_t const *t)
{
char str[80];
#if 0 /* %c is too locale-dependent. */
if (strftime (str, 40, "%c", localtime (t)) > 0)
#else
if (nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z",
localtime (t), 0, 0) > 0)
#endif
fputs (str, stdout);
else
printf ("Cannot calculate human readable time, sorry");
}
/* print statfs info */
static void
print_statfs (char *pformat, char m, char const *filename,
void const *data)
{
STRUCT_STATVFS const *statfsbuf = data;
switch (m)
{
case 'n':
strcat (pformat, "s");
printf (pformat, filename);
break;
case 'i':
#if HAVE_STRUCT_STATXFS_F_FSID___VAL
strcat (pformat, "x %-8x");
printf (pformat, statfsbuf->f_fsid.__val[0], /* u_long */
statfsbuf->f_fsid.__val[1]);
#else
strcat (pformat, "Lx");
printf (pformat, statfsbuf->f_fsid);
#endif
break;
case 'l':
strcat (pformat, NAMEMAX_FORMAT);
printf (pformat, SB_F_NAMEMAX (statfsbuf));
break;
case 't':
#if HAVE_STRUCT_STATXFS_F_TYPE
strcat (pformat, "lx");
printf (pformat, (long int) (statfsbuf->f_type)); /* no equiv. */
#else
fputc ('*', stdout);
#endif
break;
case 'T':
strcat (pformat, "s");
printf (pformat, human_fstype (statfsbuf));
break;
case 'b':
strcat (pformat, PRIdMAX);
printf (pformat, (intmax_t) (statfsbuf->f_blocks));
break;
case 'f':
strcat (pformat, PRIdMAX);
printf (pformat, (intmax_t) (statfsbuf->f_bfree));
break;
case 'a':
strcat (pformat, PRIdMAX);
printf (pformat, (intmax_t) (statfsbuf->f_bavail));
break;
case 's':
strcat (pformat, "ld");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -