/*  double/dbmode.c	changes compression algorithm of DouBle file
 *  8 Mar 1994, Heavily changed in Dec 1994
 *  Copyright (C) 1994 Jean-Marc Verbavatz  <verbavatz@achaz.saclay.cea.fr>
 *
 *  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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/double.h>

struct dble_device db;
struct dble_info info;
extern struct db_header dbh;
extern int fd;

int permanent = 0;

void read_opt(char *name, char *s)
{
	while(*s) {
		switch(*s) {
			case 'p': permanent = 1;
				  break;
			case 0:	  return;
			default:  usage(name);
		}
		s++;
	}
}

main(argc, argv)
int argc;
char **argv;
{
char *file = NULL;
struct stat statbuf;
int i, mode = -1;

for(i = 1; i < argc; i++)
	switch(*argv[i]) {
		case '-': read_opt(argv[0], argv[i]+1);
			  break;
		default: if(file == NULL) {
			 	file = argv[i];
			 	break;
			 }
			 if(mode == -1)
				mode = atoi(argv[i]);
			 else mode = -1;
			 if(mode == -1)
				usage(argv[0]);
	}
if(file == NULL) usage(argv[0]);
if(stat(file, &statbuf)<0) usage(argv[0]);
if(S_ISREG(statbuf.st_mode) && !permanent) usage(argv[0]);

if(permanent) {
	if(!db_open(&db, file)) usage(argv[0]);

	printf("DouBle device version %d.%d\n", dbh.version>>8, dbh.version&0xff);

	if(dbh.version < 3 && mode == -1)
		printf("Old device; new mode recommended\n");
	if(dbh.version > 4) {
		fprintf(stderr, "%s is older than device\n", argv[0]);
		mode = -1;
	}
	printf("Current default compression algorithm: %d\n", dbh.code);
	switch(mode) {
		case 10:
		case 102:
		case 212:
		case 312: dbh.version = 2;
		case 11:
		case 12:
		case 13: dbh.version = 3;
		case 0:
		case 1:   dbh.code = mode;
			  lseek(fd, 0L, 0);
			  write(fd, &dbh, sizeof(dbh));
			  printf("Algorithm changed to: %d\n", mode);
		case -1:  /* Just report some info */
			  printf("Total compressed Space: %ld KB\n", (dbh.iblocks*dbh.isize)>>10);
			  printf("Total Space: %ld KB\n", (dbh.oblocks*dbh.osize)>>10);
			  break;
		default:  fprintf(stderr, "Invalid mode\n");
			  usage(argv[0]);
	}
	db_close(&db, 1);
} else {
	fd = open(file, O_RDONLY);
	if(fd < 0) usage(argv[0]);
	if(ioctl(fd, DBLE_GET_STATUS, &info)) usage(argv[0]);
	printf("Current compression algorithm: %d\n", info.code);
	switch(mode) {
		case 0:
		case 1:
		case 10:
		case 102: mode = 11; goto new_mode;
		case 212: mode = 12; goto new_mode;
		case 312: mode = 13; goto new_mode;
	new_mode:
		case 11:
		case 12:
		case 13:  info.code = mode;
			  ioctl(fd, DBLE_SET_STATUS, &info);
			  printf("Algorithm changed to: %d\n", mode);
		case -1:  /* Just report some info */
			  printf("Total compressed Space: %ld KB\n", (info.iblocks*info.isize)>>10);
			  printf("Total Space: %ld KB\n", (info.oblocks*info.osize)>>10);
			  printf("Free compressed space: %ld KB\n", (info.free_blocks*info.isize)>>10);
			  printf("Current mount flags: %lx\n", info.fs_flags);
			  break;
		default:  fprintf(stderr, "Invalid mode\n");
			  usage(argv[0]);
	}
	close(fd);
}
}

usage(char *s)
{
if(errno) perror(s);
printf("usage: %s -p device_file [mode]\n", s);
printf("\t\tChange default compression algorithm\n");
printf("\t\tUse only on not mounted device_file\n");
printf("\n       %s /dev/double[0-7] [mode]\n", s);
printf("\t\tChange current compression algorithm\n");
printf("\t\tUse only on mounted device_file\n");
printf("\n\tmode:\n");
printf("\t\t0:   no compression\n");
printf("\t\t1:   LZW (not recommended)\n");
printf("\t\t10:  predictor\n");
printf("\t\t11: LZV\n");
printf("\t\t12: LZRW2\n");
printf("\t\t13: LZRW3A\n\n");
exit(1);
}
