#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int dir_ignore = 0;

void usage(void)
{
    fprintf(stderr, "usage: filesize [-b] [-k] [-m] [-h] [files...]\n");
    exit(1);
}

int filesize(const char *path) {
    struct stat s;

    if(path == NULL || strcmp(path, "-") == 0) {
	int i, n;
	char buff[BUFSIZ];
	n = 0;
	while((i = read(0, buff, sizeof(buff))) > 0)
	    n += i;
	if(i == -1)
	    return -1;
	return n;
    }

    if(stat(path, &s) == -1)
	return -1;
    if(dir_ignore && S_ISDIR(s.st_mode))
	return 0;
    return s.st_size;
}

void dispsize(char *path, int size, int base)
{
    switch(base) {
      case 'k':
	printf("%8d ", (int)(size / 1024.0 + 0.5));
	break;
      case 'm':
	printf("%8d ", (int)(size / 1024.0 / 1024.0 + 0.5));
	break;
      default:
	printf("%8d ", size);
	break;
    }

    if(path != NULL)
	printf("%s", path);
    printf("\n");
}

int main(int argc, char **argv)
{
    int base = 'b';
    char **files;
    int nf;
    int size;

    argv++;
    argc--;

    while(argc >= 0) {
	if(strcmp(*argv, "-b") == 0)
	    base = 'b';
	else if(strcmp(*argv, "-k") == 0)
	    base = 'k';
	else if(strcmp(*argv, "-m") == 0)
	    base = 'm';
	else if(strcmp(*argv, "-D") == 0)
	    dir_ignore = 1;
	else if(strcmp(*argv, "-h") == 0)
	    usage();
	else if(strcmp(*argv, "-") == 0)
	    break;
	else if(**argv == '-')
	    usage();
	else
	    break;
	argv++;
	argc--;
    }

    files = argv;
    nf = argc;

    if(nf <= 0) {
	if((size = filesize(NULL)) == -1)
	    perror("(stdin)");
	else
	    dispsize(NULL, size, base);
    } else {
	int total = 0;;
	while(nf > 0) {
	    if((size = filesize(*files)) == -1)
		perror(*files);
	    else {
		dispsize(*files, size, base);
		total += size;
	    }
	    files++;
	    nf--;
	}
	dispsize("total", total, base);
    }
    return 0;
}
