/*
 *  ntchange.c
 *
 *  Copyright (C) 1995 Martin von Löwis
 */

#include <stdio.h>
#include <getopt.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ntfs.h"
#include "config.h"
/* glibc string.h does not define a memcpy prototype */
void* memcpy(void*,const void*,size_t);

char *short_opts="f:s:";
struct option options[]={
	{"filesystem",1,0,'f'},
	{"source",1,0,'s'}
};

int usage()
{
	fprintf(stderr,"ntchange [-f device] -s source [-o offset] [directory/]filename\n");
	return 1;
}

/* print the file ino on stdout */
void ntfs_change_file(ntfs_inode *ino,char *buf,int offset,int count)
{
	int position,len;
	position=0;
	/* write to the unnamed data attribute */
	ntfs_write_attr(ino,AT_DATA,NULL,
		offset,buf,count,memcpy);
}

/* answer the MFT record number for file name in directory ino */
int ntfs_find_file(ntfs_inode* ino,char *name)
{
	char item[1000];
	if(!ntfs_getdir_byname(ino,name,strlen(name),item))return -1;
	return *(int*)item;
}

int main(int argc,char *argv[])
{
	int c;
	char *device=0;
	char *source=0;
	char *name;
	void *buf;
	int fsource;
	ntfs_inode ino;
	int inum;
	int offset;
	struct stat sb;

	opterr=1;
	while((c=getopt_long(argc,argv,short_opts,options,NULL))>0)
	switch(c)
	{
		case 'f': device=strdup(optarg);break;
		case 's': source=strdup(optarg);break;
		case 'o': offset=strtol(optarg,0);break;
	}
	name=argv[optind];
	if(!ntfs_open_volume(device,0,1,0))return 1;
	if(!source)
		return usage();
	fsource=open(source,O_RDONLY);
	if(fsource==-1)
	{
		perror(source);
		return 1;
	}
	if(fstat(fsource,&sb)!=0)
	{
		perror(source);
		return 1;
	}
	buf=malloc(sb.st_size);
	if(!buf)
	{
		perror(argv[0]);
		return 1;
	}
	if(read(fsource,buf,sb.st_size)!=sb.st_size)
	{
		perror(argv[0]);
		return 1;
	}
	inum=5;
	/* walk the directory tree */
	do{
		char *next;
		ntfs_init_inode(&ino,the_vol,inum);
		if(!name || !*name)break;
		next=strchr(name,'/');
		if(next){
			*next='\0';
			next++;
		}
		inum=ntfs_find_file(&ino,name);
		if(inum==-1){
			printf("%s not found\n",name);
			return 1;
		}
		name=next;
	}while(1);
	ino.i_number=inum;
	ntfs_change_file(&ino,buf,offset,sb.st_size);
}

