00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 # define ALLDEF
00022
00023 # include <sys/types.h>
00024 # include <errno.h>
00025 # include <limits.h>
00026 # include <stdio.h>
00027 # include <stdlib.h>
00028 # include <unistd.h>
00029 # include <string.h>
00030 # include <time.h>
00031 # include <sys/stat.h>
00032 # define addr(x) ((void*) &sbuf.x)
00033 # define size(x) sizeof(sbuf.x)
00034 # define equal(s, t) (strcmp(s, t) == 0)
00035 # ifndef PATH_MAX
00036 # define PATH_MAX 1024
00037 # endif
00038 # undef LS_ADDS_SPACE
00039
00040
00041 # ifndef _MINIX
00042 # define BSD
00043 # endif
00044
00045 # ifndef S_IREAD
00046 # define S_IREAD S_IRUSR
00047 # define S_IWRITE S_IWUSR
00048 # define S_IEXEC S_IXUSR
00049 # endif
00050
00051 char * arg0;
00052 struct stat sbuf;
00053 extern int errno;
00054 int first_file= 1;
00055 #ifndef S_IFLNK
00056 #define lstat stat
00057 #endif
00058
00059 struct field {
00060 char* f_name;
00061 u_char* f_addr;
00062 u_short f_size;
00063 u_short f_print;
00064 } fields[] = {
00065 { "dev", addr(st_dev), size(st_dev), 0 },
00066 { "ino", addr(st_ino), size(st_ino), 0 },
00067 { "mode", addr(st_mode), size(st_mode), 0 },
00068 { "nlink", addr(st_nlink), size(st_nlink), 0 },
00069 { "uid", addr(st_uid), size(st_uid), 0 },
00070 { "gid", addr(st_gid), size(st_gid), 0 },
00071 { "rdev", addr(st_rdev), size(st_rdev), 0 },
00072 { "size", addr(st_size), size(st_size), 0 },
00073 { "Atime", addr(st_atime), size(st_atime), 0 },
00074 { "atime", addr(st_atime), size(st_atime), 0 },
00075 { "Mtime", addr(st_mtime), size(st_mtime), 0 },
00076 { "mtime", addr(st_mtime), size(st_mtime), 0 },
00077 { "Ctime", addr(st_ctime), size(st_ctime), 0 },
00078 { "ctime", addr(st_ctime), size(st_ctime), 0 },
00079 # ifdef BSD
00080 { "blksize", addr(st_blksize), size(st_blksize), 0 },
00081 { "blocks", addr(st_blocks), size(st_blocks), 0 },
00082 # endif
00083 { NULL, 0, 0, 0 },
00084 };
00085
00086 void printstat(struct stat *sbuf, int nprint);
00087 void printit(struct stat* sb, struct field* f, int n);
00088 void rwx(mode_t mode, char *bit);
00089 void usage(void);
00090
00091 int do_readlink=0;
00092
00093 int main(int ac, char** av)
00094 {
00095 int i, j, nprint = 0, files = 0;
00096 char buf[PATH_MAX], *check;
00097 int sym=0, ret=0, from_stdin = 0;
00098 int err;
00099 u_long fd;
00100
00101 if ((arg0 = strrchr(av[0], '/')) == NULL) arg0 = av[0]; else arg0++;
00102 #ifdef S_IFLNK
00103 if (equal(arg0, "lstat")) sym = 1;
00104 if (equal(arg0, "readlink")) do_readlink = 1;
00105 #endif
00106
00107 if (ac > 1 && equal(av[i = 1], "-"))
00108 i++, from_stdin++;
00109
00110 for (i= 1; i<ac; i++) {
00111 if (av[i][0] == '-') {
00112 if (equal(av[i], "-")) {
00113 from_stdin= 1;
00114 files++;
00115 continue;
00116 }
00117 if (equal("-all", av[i])) {
00118 for (j=0; fields[j].f_name; j++)
00119 nprint++, fields[j].f_print++;
00120 continue;
00121 }
00122 if (equal("-s", av[i])) {
00123 #ifdef S_IFLNK
00124 sym=1;
00125 #endif
00126 continue;
00127 }
00128 fd = strtoul(av[i]+1, &check, 0);
00129 if (check != av[i]+1 && *check == '\0')
00130 {
00131 files++;
00132 continue;
00133 }
00134 for (j=0; fields[j].f_name; j++)
00135 if (equal(fields[j].f_name, &av[i][1])) {
00136 nprint++, fields[j].f_print++;
00137 break;
00138 }
00139 if (!fields[j].f_name) {
00140 if (!equal("-?", av[i])) {
00141 fprintf(stderr, "stat: %s: bad field\n", av[i]);
00142 }
00143 usage();
00144 }
00145 }
00146 else
00147 files++;
00148 }
00149 if (!nprint) {
00150 # ifndef ALLDEF
00151 usage();
00152 # else
00153 for (j=0; fields[j].f_name; j++)
00154 nprint++, fields[j].f_print++;
00155 # endif
00156 }
00157
00158 if (from_stdin)
00159 files++;
00160
00161 if (files == 0) {
00162 if(do_readlink) return 0;
00163 for (i= 0; i<OPEN_MAX; i++) {
00164 err= fstat(i, &sbuf);
00165 if (err == -1 && errno == EBADF)
00166 continue;
00167 if (err == 0) {
00168 if (!first_file) fputc('\n', stdout);
00169 printf("fd %d:\n", i);
00170 printstat(&sbuf, nprint);
00171 }
00172 else {
00173 fprintf(stderr, "%s: fd %d: %s\n", arg0, i, strerror(errno));
00174 ret= 1;
00175 }
00176 }
00177 exit(ret);
00178 }
00179
00180 for (i=1; i<ac; i++) {
00181 if (equal(av[i], "-")) {
00182 while (fgets(buf, sizeof(buf), stdin)) {
00183 char *p= strchr(buf, '\n');
00184 if (p) *p= 0;
00185 #ifdef S_IFLNK
00186 if(do_readlink) {
00187 char sbuf[300];
00188 int n;
00189 if((n=readlink(buf, sbuf, sizeof(sbuf)-1)) < 0) {
00190 perror(buf);
00191 continue;
00192 }
00193 sbuf[n] = '\0';
00194 printf("%s: %s\n", buf, sbuf);
00195 continue;
00196 }
00197 #endif
00198 if (!sym) err= stat(av[i], &sbuf);
00199 if (sym || (err != 0 && errno == ENOENT)) {
00200 err= lstat(av[i], &sbuf);
00201 }
00202 if (err == -1) {
00203 fprintf(stderr, "%s: %s: %s\n",
00204 arg0, av[i], strerror(errno));
00205 ret= 1;
00206 }
00207 else {
00208 if (!first_file) fputc('\n', stdout);
00209 printf("%s:\n", buf);
00210 printstat(&sbuf, nprint);
00211 }
00212 }
00213 continue;
00214 }
00215 if (av[i][0] == '-') {
00216 fd= strtoul(av[i]+1, &check, 10);
00217 if (check == av[i]+1 || *check != '\0') continue;
00218 if (fd >= INT_MAX) {
00219 err= -1;
00220 errno= EBADF;
00221 }
00222 else {
00223 err= fstat((int) fd, &sbuf);
00224 }
00225 if (err != -1) {
00226 if (!first_file) fputc('\n', stdout);
00227 if (files != 1) printf("fd %lu:\n", fd);
00228 printstat(&sbuf, nprint);
00229 }
00230 else {
00231 fprintf(stderr, "fd %lu: %s\n", fd, strerror(errno));
00232 ret= 1;
00233 }
00234 continue;
00235 }
00236 if(do_readlink) {
00237 char sbuf[300];
00238 int n;
00239 if((n=err=readlink(av[i], sbuf, sizeof(sbuf)-1)) < 0) {
00240 perror(av[i]);
00241 continue;
00242 }
00243 sbuf[n] = '\0';
00244 printf("%s: %s\n", av[i], sbuf);
00245 continue;
00246 }
00247 if (!sym) err= stat(av[i], &sbuf);
00248 if (sym || (err != 0 && errno == ENOENT)) err= lstat(av[i], &sbuf);
00249 if (err != -1) {
00250 if (!first_file) fputc('\n', stdout);
00251 if (files != 1) printf("%s:\n", av[i]);
00252 printstat(&sbuf, nprint);
00253 }
00254 else {
00255 fprintf(stderr, "%s: %s: %s\n", arg0, av[i], strerror(errno));
00256 ret= 1;
00257 }
00258 }
00259 exit(ret);
00260 }
00261
00262
00263
00264
00265 void printstat(struct stat *sbuf, int nprint)
00266 {
00267 int j;
00268 int first_field= 1;
00269
00270 for (j=0; fields[j].f_name; j++) {
00271 if (fields[j].f_print) {
00272 if (!first_field) fputc('\n', stdout);
00273 printit(sbuf, &fields[j], nprint);
00274 first_field= 0;
00275 }
00276 }
00277 fputc('\n', stdout);
00278 first_file= 0;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 void printit(struct stat* sb, struct field* f, int n)
00291 {
00292 if (n > 1)
00293 printf("%s: ", f->f_name);
00294 if (equal(f->f_name, "mode")) {
00295
00296 char bit[11];
00297
00298 printf("%07lo, ", (u_long) sb->st_mode);
00299
00300 strcpy(bit, "----------");
00301
00302 switch (sb->st_mode&S_IFMT) {
00303 case S_IFDIR: bit[0]='d'; break;
00304 # ifdef S_IFFIFO
00305 case S_IFFIFO: bit[0]='p'; break;
00306 # endif
00307 case S_IFCHR: bit[0]='c'; break;
00308 case S_IFBLK: bit[0]='b'; break;
00309 # ifdef S_IFSOCK
00310 case S_IFSOCK: bit[0]='S'; break;
00311 # endif
00312 # ifdef S_IFMPC
00313 case S_IFMPC: bit[0]='C'; break;
00314 # endif
00315 # ifdef S_IFMPB
00316 case S_IFMPB: bit[0]='B'; break;
00317 # endif
00318 # ifdef S_IFLNK
00319 case S_IFLNK: bit[0]='l'; break;
00320 # endif
00321 }
00322 rwx(sb->st_mode, bit+1);
00323 rwx(sb->st_mode<<3, bit+4);
00324 rwx(sb->st_mode<<6, bit+7);
00325 if (sb->st_mode&S_ISUID) bit[3]='s';
00326 if (sb->st_mode&S_ISGID) bit[6]='s';
00327 if (sb->st_mode&S_ISVTX) bit[9]='t';
00328 printf("\"%s\"", bit);
00329 }
00330
00331 else if (equal("Ctime", f->f_name)) {
00332 printf("%.24s (%lu)", ctime(&sb->st_ctime), (u_long) sb->st_ctime);
00333 f[1].f_print= 0;
00334 }
00335 else if (equal("Mtime", f->f_name)) {
00336 printf("%.24s (%lu)", ctime(&sb->st_mtime), (u_long) sb->st_mtime);
00337 f[1].f_print= 0;
00338 }
00339 else if (equal("Atime", f->f_name)) {
00340 printf("%.24s (%lu)", ctime(&sb->st_atime), (u_long) sb->st_atime);
00341 f[1].f_print= 0;
00342 }
00343 else if (equal("ctime", f->f_name)) {
00344 printf("%lu", (u_long) sb->st_ctime);
00345 }
00346 else if (equal("mtime", f->f_name)) {
00347 printf("%lu", (u_long) sb->st_mtime);
00348 }
00349 else if (equal("atime", f->f_name)) {
00350 printf("%lu", (u_long) sb->st_atime);
00351 }
00352 else {
00353 switch (f->f_size) {
00354 case sizeof(char):
00355 printf("%d", * (u_char *) f->f_addr);
00356 break;
00357 case sizeof(short):
00358 printf("%u", (u_int) * (u_short *) f->f_addr);
00359 break;
00360 #if INT_MAX != SHRT_MAX
00361 case sizeof(int):
00362 printf("%u", * (u_int *) f->f_addr);
00363 break;
00364 #endif
00365 #if LONG_MAX != INT_MAX && LONG_MAX != SHRT_MAX
00366 case sizeof(long):
00367 printf("%lu", * (u_long *) f->f_addr);
00368 break;
00369 #endif
00370 default:
00371 fprintf(stderr, "\nProgram error: bad '%s' field size %d\n",
00372 f->f_name, f->f_size);
00373 break;
00374 }
00375 }
00376 }
00377
00378 void rwx(mode_t mode, char *bit)
00379 {
00380 if (mode&S_IREAD) bit[0]='r';
00381 if (mode&S_IWRITE) bit[1]='w';
00382 if (mode&S_IEXEC) bit[2]='x';
00383 }
00384
00385 void usage(void)
00386 {
00387 fprintf(stderr,
00388 "Usage: %s [-] [-fd] [-all] [-s] [-field ...] [file1 ...]\n",
00389 arg0);
00390 exit(1);
00391 }