/*
 * John Buck -- 8/83 -- This is it. The program to undo an 'rm' command.
 *
 * Saves the last n free blocks on the filesystem named... Has certain
 * problems (indirect free's, filesystem activity, etc)  but when it works
 * it's a lifesaver.  (It also makes you look like a miracle worker, for
 * job security!)
 */
#include "sys/types.h"
#include "sys/param.h"
#include "sys/filsys.h"

struct filsys sblock;
char	buf[512];

main(c,v)
char **v;
{
	register int n, f, nl;
	int fd;
	f = nl = 0;
	n = getgid();

	if(n != 2 && n != 3 && n){
		printf("\nAccess denied.\n\n");
		exit(-1);
	}

	if(c != 3){
		printf("Usage: save number-of-blocks special\n");
		exit(1);
	}

	n = atoi(*++v);
	if(n < 1 || n > 500){
		printf("Too many blocks -- get the first few, then modify program\n");
		exit(3);
	}
	if((fd = open(*++v, 0)) == -1){
		printf("Can not open %s\n", *v);
		exit(1);
	}

	lseek(fd, 512L, 0);
	sync();
	if(read(fd, &sblock, sizeof sblock) != sizeof sblock){
		printf("Super-block read error\n");
		exit(2);
	}

loop:
	f = sblock.s_nfree-1;
	while(n && f){
		lseek(fd, sblock.s_free[f--]*512, 0);
		if(read(fd, buf, 512) != 512){
			printf("Read error block %u\n", sblock.s_free[f+1]);
			close(fd);
			exit(4);
		}
		write(1, buf, 512);
		n--;
	}
	if(n == 0){
		close(fd);
		if(nl)printf("\n\n%d blocks lost due to indirect frees\n\n");
		exit(0);
	}

	if(sblock.s_free[0] == 0){
		printf("\n\n\nEnd of free list reached.\n\n");
		close(fd);
		exit(4);
	}

	lseek(fd, sblock.s_free[0]*512, 0);
	n--;
	nl++;
	read(fd, &sblock.s_nfree, 204);
	if(n)goto loop;
	close(fd);
	printf("Lost last block due to indirect free\n\n");
	exit(0);
}

