#include "mdirent.cpp"

/* Вывод информации об использовании пограммы ################################*/
void ShowHelp(int lang) {
if (lang==0)
	printf("\n\
Usage: fat12.exe options filename\n\
\n\
  filename - Name of the floppy image file.\n\
  options  - One of the following:\n\
\
\t-r\tPrint Russian help.\n\
\t-b\tPrint BOOT sector info.\n\
\t-v\tPrint list of all files.\n\
\t-l\tPrint list of files in root directory.\n\
\t-x\tExtract all files.\n\
\n\
Using: fat12.exe options filename param1\n\
\n\
\t-l\tPrint list of all files in <param1> directory.\n\
\t-e\tExtract  file <param1> without path\n\
\t-x\tExtract <param1> file (or recursive directory) with path\n\
\t-d\tDelete file <param1>.\n\
\t-a\tAdd file <praram1>.\n\
\n\
Usage: fat12.exe options filename param1 param2\n\
\n\
\t-md     Create directory <param2> in <param1>\n\
\n\
(C) Mikhail Krivyy. Mail me for bugs: http://mikhail.krivyy.com/feedback/\n\
(C) Spellchecking Sergey Popov and Lynx :)\n\
");
else
	printf("\n\
Использование: fat12.exe options filename\n\
\n\
  filename - Имя файла образа дискеты.\n\
  options  - Один из следующих параметров:\n\
\n\
\t-r\tВывести подсказку на русском языке (то, что вы сейчас видите).\n\
\t-b\tВывести информацию, хранящуюся в BOOT секторе.\n\
\t-v\tВывести список всех файлов.\n\
\t-l\tВывести список всех файлов корневого каталога.\n\
\t-x\tРекурсивно извлечь все файлы.\n\
\n\
Использование: fat12.exe options filename param1\n\
\n\
\t-l\tВывести список файлов из каталога <param1>.\n\
\t-e\tИзвлечь файл <param1> без сохранения путей.\n\
\t-x\tИзвлечь файл <param1> (или каталог со всем его содержимым).\n\
\t-d\tУдалить файл <param1>.\n\
\t-a\tДобавить файл <praram1> в образ диска.\n\
\n\
Использование: fat12.exe options filename param1 param2\n\
\n\
\t-md\tСоздать каталог <param2> в каталоге <param1>\n\
\n\
(C) Mikhail Krivyy. Найдете баги, пишите: http://mikhail.krivyy.com/feedback/\
");
	}

/* Вывод информации о boot'e #################################################*/
void print_Boot(void) {
	printf("\nBoot information:");
	printf("\n");
	printf("\n\tJump adress.....................0x%x",boot.jump[2]+256*boot.jump[1]);
	printf("\n\tOEM name........................%s",boot.oem);
	printf("\n\tBytes per sector................%d",boot.sector_size);
	printf("\n\tSectors per cluster.............%d",boot.cluster_size);
	printf("\n\tSectors reserved................%d",boot.sector_reserved);
	printf("\n\tFAT count.......................%d",boot.fat_count);
	printf("\n\tRoot size.......................%d",boot.root_size);
	printf("\n\tTotal sectors...................%d",boot.sector_total);
	printf("\n\tMedia...........................%d",boot.media);
	printf("\n\tFAT size........................%d",boot.fat_size);
	printf("\n\tSectors per track...............%d",boot.sectors_per_track);
	printf("\n\tHead count......................%d",boot.head_count);
	printf("\n\tHidden secotrs..................%d",boot.sectors_hidden);
	printf("\n");
}

/* Вывод каталога ############################################################*/
void dir(char *curdir) {
	DirectoryEntry *dir;
	char str[16];

	m_DIR *d=m_opendir(curdir);
	if (!d) return;
	dir=(DirectoryEntry *)malloc(sizeof(DirectoryEntry));
	while (m_readdir(d,dir)!=NULL) {
		bool need=false;
		if (dir->attr_volume==0 && dir->name[0]!=0 && (dir->name[0]!=32 || dir->ext[0]!=32)) need=true;
		if (memcmp(dir->name,".       ",8)==0) need=false;
		if (memcmp(dir->name,"..      ",8)==0) need=false;
		if (dir->name[0]==229) need=false; /* Удаленый файл */
		if (need) {
			if (dir->attr_archv==1   ) putchar(65); else putchar(45);
			if (dir->attr_dir==1     ) putchar(68); else putchar(45);
			if (dir->attr_volume==1  ) putchar(86); else putchar(45);
			if (dir->attr_system==1  ) putchar(83); else putchar(45);
			if (dir->attr_hidden==1  ) putchar(72); else putchar(45);
			if (dir->attr_readonly==1) putchar(79); else putchar(45);
			if (dir->attr_dir==0)	printf("  %9d",dir->filesize);
			else printf("      <DIR>");
			printf("  %04d-%02d-%02d %02d:%02d:%02d",1980+dir->date.year,dir->date.month,dir->date.day,dir->time.hour,dir->time.min,dir->time.sec*2);
			printf("  [%4d]",dir->ClstrNo);
			memset(str,0,16);memcpy(str,dir->name,8);
			int k=0;while (str[k]!=32 && str[k]!=0) k++;str[k]=0;
			if (!d->root) printf("  %s\\%s",curdir,str);
			else printf("  %s",str);
			memset(str,0,16);memcpy(str,dir->ext,3);
			k=0;while (str[k]!=32 && str[k]!=0) k++;str[k]=0;
			if (strlen(str)!=0) printf(".%s\n",str); else printf("\n");
			}
		}
	free(dir);
	m_closedir(d);
	}

/* Рекурсивный вывод списка файлов всех ######################################*/
void print_All(char *path) {
	DirectoryEntry *dirent;
	char nname[256];
	char str[16];

	dir(path);
	m_DIR *d=m_opendir(path);
	if (!d) return;
	dirent=(DirectoryEntry *)malloc(sizeof(DirectoryEntry));
	while (m_readdir(d,dirent)!=NULL) {
		bool need=false;
		if (dirent->attr_dir==1) need=true;
		if (memcmp(dirent->name,".       ",8)==0) need=false;
		if (memcmp(dirent->name,"..      ",8)==0) need=false;
		if (dirent->name[0]==229) need=false; /* Удаленный файл */
		if (need) {
			strcpy(nname,path);
			if (strlen(path)!=0) strcat(nname,"\\");
			char *sname=get_NormalName(dirent->name,dirent->ext);
			strcat(nname,sname);
			free(sname);
			print_All(nname);
			}
		}
	m_closedir(d);
	free(dirent);
	}

/* Извлечение файлов без путей ###############################################*/
void extract(char* filename) {
	char buff[1024];
	int size;

	m_FILE *fp=m_fopen(filename);

	if (!fp) { /* Если файл не удалось открыть */
		printf("\n File %s not found !!!\n",filename);
		return;
		}

	/* Теперь проучим имя файла без пути */
	char *fname=strrchr(filename,92);
	if (fname) {
		fname[0]=0;
		fname++;
		}
	else {
		fname=filename;
		}

	if (strlen(fname)<1) {
		printf("\nNo file specified !!!\n",fname);
		m_fclose(fp);
		return;
		}

	FILE *fw=fopen(fname,"wb");
	do {
		size=m_fread(buff,1,sizeof(buff),fp);
		fwrite(buff,1,size,fw);
	} while (size!=0);
	m_fclose(fp);
	fclose(fw);
	}

/* Извлечение файлов с путями ################################################*/
void xextract(char* filename) {
	char buff[1024];
	int size;

	m_FILE *fp=m_fopen(filename);

	if (!fp) { /* Если файл не удалось открыть */
		/* Если это каталог, то извлекаем рекурсивно все файлы из подкаталогов */
		m_DIR *d=m_opendir(filename);
		if (d) {
			DirectoryEntry* dirent;
			dirent=(DirectoryEntry *)malloc(sizeof(DirectoryEntry));
			while (m_readdir(d,dirent)!=NULL) {
				if (dirent->attr_volume==0) {
					char *sname=get_NormalName(dirent->name,dirent->ext);
					if (sname[0]!=0 && strcmp(sname,"..")!=0 && strcmp(sname,".")!=0) {
						char *newfullname=(char*)malloc(260);
						strcpy(newfullname,filename);
						if (newfullname[0]!=0) strcat(newfullname,"\\");
						strcat(newfullname,sname);
						xextract(newfullname);
						free(newfullname);
						free(sname);
						}
					}
				}
			m_closedir(d);
			free(dirent);
			}
		else
			printf("\n File %s not found !!!\n",filename);
		return;
		}

	if (filename[0]!=0) {
		/* Теперь получим имя файла без пути */
		char *dfilename=strdup(filename);
		char *fname=strrchr(filename,92);
		if (fname) {
			fname[0]=0;
			DIR *d=opendir(filename);
			if (!d) {
				char *w=filename;
				while (w != NULL) {
					char *we = strchr(w,92);
					if (we) {
						we[0]=0;

						int res=mkdir(filename);
						if (res!=0) printf("Error creating directory...");
						we[0]=92;
						w=we+1;
						} else w=NULL;
					} // of while
				int res=mkdir(filename);
				if (res!=0) printf("Error creating directory...");
				} else closedir(d);
			}

		FILE *fw=fopen(dfilename,"wb");
		free(dfilename);
		if (fw) {
			do {
				size=m_fread(buff,1,sizeof(buff),fp);
				fwrite(buff,1,size,fw);
			} while (size!=0);
			fclose(fw);
			}
		else printf("\nError creating file...\n");
		m_fclose(fp);
		}
	}

int createdisk(char *fname,char *bootname) {
	if (fname[0]==0) return(MERROR_FILENAME_MUST_BE_SPECIFIED);
	FILE *fw=fopen(fname,"wb");

	BootRecord boot;
	boot.jump[2]=0x90;boot.jump[1]=0x1C;boot.jump[0]=0xEB;
	memcpy(boot.oem,"CNFAT12!",8);
	boot.sector_size=512;
	boot.cluster_size=1;
	boot.sector_reserved=1;
	boot.fat_count=2;
	boot.root_size=224;
	boot.sector_total=2880;
	boot.media=240;
	boot.fat_size=9;
	boot.sectors_per_track=18;
	boot.head_count=2;
	boot.sectors_hidden=0;
	fwrite(&boot,1,sizeof(boot),fw);

	char *buff=(char*)malloc(boot.sector_size);
	if (buff) {	
		memset(buff,0,boot.sector_size);

		int bloadersize;
		if (!bootname) { /* Если не задан загрузчик */
			bloadersize=sizeof(boot_loader);
			fwrite(&boot_loader,1,bloadersize,fw);
			}
		else { /* Если задан загрузчик */
			FILE *fb=fopen(bootname,"rb");
			if (!fb) {free(buff);return(MERROR_FILE_NOT_FOUND);}
			fseek(fb,0x7B1E,SEEK_SET);
			bloadersize=fread(buff,1,boot.sector_size,fb);
			fwrite(buff,1,bloadersize,fw);
			fclose(fb);
			}

		memset(buff,0,boot.sector_size);
		/* Пишем boot */
		fwrite((void*)buff,1,boot.sector_size-sizeof(boot)-bloadersize,fw);

		/* Пишем первый FAT */
		buff[0]=0xF0;buff[1]=0xFF;buff[2]=0xFF;
		fwrite((void*)buff,1,boot.sector_size,fw);
		buff[0]=0;buff[1]=0;buff[2]=0;
		for (int i=1;i<9;i++) fwrite((void*)buff,1,boot.sector_size,fw);

		/* Пишем второй FAT */
		buff[0]=0xF0;buff[1]=0xFF;buff[2]=0xFF;
		fwrite((void*)buff,1,boot.sector_size,fw);
		buff[0]=0;buff[1]=0;buff[2]=0;
		for (int i=1;i<9;i++) fwrite((void*)buff,1,boot.sector_size,fw);

		/* Пишем каталог */
		for (int i=0;i<(boot.root_size*32)/boot.sector_size;i++) fwrite((void*)buff,1,boot.sector_size,fw);

		/* Пишем все остальное */
		int count=boot.sector_total-((boot.root_size*32)/boot.sector_size+boot.fat_count*boot.fat_size+boot.sector_reserved);

		memset(buff,0xF6,boot.sector_size);
		for (int i=0;i<count;i++) fwrite((void*)buff,1,boot.sector_size,fw);

		fclose(fw);
		free(buff);
		}
	return(MERROR_OK);
	}

/* Удаление файла ############################################################*/
int deletefile(char *filename) {
	printf("Deleting file %s...\n",filename);
	m_DIR *d;
	char *path;
	Word cc,c_sclstr,c_ric;
	bool root;

	char *ll=strrchr(filename,92);
	if (!ll) {
        d=m_opendir("");
        path=NULL;
        }
	else {
		path=filename;
		ll[0]=0;
		filename=ll+1;
		d=m_opendir(path);
		}

	if (!d || filename[0]==0) return(MERROR_FILE_NOT_FOUND);

	DirectoryEntry* dirent;
	bool find=false;
	dirent=(DirectoryEntry *)malloc(sizeof(DirectoryEntry));
	while (m_readdir(d,dirent)!=NULL) {
		char *sname=get_NormalName(dirent->name,dirent->ext);
		if (strcmp(sname,filename)==0 && strcmp(sname,"..")!=0 && strcmp(sname,".")!=0 && dirent->attr_volume==0) {
			if (dirent->attr_dir==1) { /* Если каталог */
				/* Рекурсивно удаляем все что есть внутри */
                char* opendirname=(char*)malloc(260);
                if (!opendirname) {
                    free(sname);
                    return(MERROR_NOT_ENOGHT_MEMORY);
                    }
                opendirname[0]=0;
                if (path) {
                    strcat(opendirname,path);
                    strcat(opendirname,"\\");
                    }
                strcat(opendirname,filename);
				m_DIR *d1=m_opendir(opendirname);

				if (!d1) {
                    free(sname);
                    return(MERROR_DIRECTORY_NOT_FOUND);
                    }
				DirectoryEntry* dirent1;
				dirent1=(DirectoryEntry *)malloc(sizeof(DirectoryEntry));
				while (m_readdir(d1,dirent1)!=NULL) {
					char *sname1=get_NormalName(dirent1->name,dirent1->ext);
					if (dirent1->name[0]!=0 && dirent1->name[0]!=229 && strcmp(sname1,".")!=0 && strcmp(sname1,"..")!=0 && dirent1->attr_volume==0) {
						char *newfilename=(char*)malloc(260);
						strcpy(newfilename,opendirname);
						strcat(newfilename,"\\");
						strcat(newfilename,sname1);
						int error=deletefile(newfilename);
						if (error!=0) return(error);
						free(newfilename);
						}
					free(sname1);
					}
				free(dirent1);
				m_closedir(d1);
                free(opendirname);
				/* Удаляем сам пустой каталог */
				find=true;
				root=d->root;
				c_ric=d->last_record_in_cluster;    /* Запись в кластере */
				cc=d->last_cluster;					/* Текущий кластер */
				c_sclstr=dirent->ClstrNo;			/* Точка входа в файл или каталог */
				}
			else { /* Если не каталог */
				find=true;
				root=d->root;
				c_ric=d->last_record_in_cluster;    /* Запись в кластере */
				cc=d->last_cluster;					/* Текущий кластер */
				c_sclstr=dirent->ClstrNo;			/* Точка входа в файл или каталог */
				}
			}
		free(sname);
		}
	free(dirent);
	m_closedir(d);

	if (!find) return(MERROR_FILE_NOT_FOUND);

	/* Исправим сначала FAT, точнее его первую копию */
	do {
  		Word nextfat=FAT[c_sclstr];
		FAT[c_sclstr]=0;
		c_sclstr=nextfat;
	} while (c_sclstr<clusters_total);
	if (boot.fat_count>0) write_FAT(1);

	/* Считаем этот самый кластер, вставим русскую "х" в начало файла и запишем обратно */
	char* cluster=(char*)malloc(boot.cluster_size*boot.sector_size);
	if (!cluster) return(MERROR_NOT_ENOGHT_MEMORY);
	if (root) sector_Read(cluster,cc);
	else cluster_Read(cluster,cc);
	cluster[c_ric*32]=229;
	if (root) sector_Write(cluster,cc);
	else cluster_Write(cluster,cc);
	
	if (boot.fat_count>1) write_FAT(2);
	free(cluster);
	return(MERROR_OK);
	}

/* Создаем каталог в уже существующем каталоге ###############################*/
int createdir(char* dirname, char* newdirname) {
	Byte *tmpcluster;
	Word find_position,find_cluster,parent_cluster;
	DirectoryEntry dirent;
	int i;
	FileDate file_d;
	FileTime file_t;
	time_t timer;
	struct tm *tblock;
	Word old_curent_cluster;
    bool root=false;

	/* Проверим, может такой каталог уже есть ? */
	char *testname=(char*)malloc(260);
	if (!testname) return(MERROR_NOT_ENOGHT_MEMORY);
	testname[0]=0;
	if (dirname[0]!=0) {
		strcat(testname,dirname);
		strcat(testname,"\\");
		}
	strcat(testname,newdirname);
	m_DIR* testdir=m_opendir(testname);
	free(testname);
	if (testdir) {
		m_closedir(testdir);
		return(MERROR_DIRECTORY_ALREADY_EXISTS);
		}

	if (!dirname || !newdirname) return(MERROR_CREATING_DIRECTORY);
	if (newdirname[0]==0) return(MERROR_CREATING_DIRECTORY);
	Word clstr=get_Cluster(dirname);
	if (clstr==0) return(MERROR_FILE_NOT_FOUND);
    if (clstr==1) { /* Если 1-ый кластер, то это корень */
		root=true;
		clstr=boot.fat_count*boot.fat_size+boot.sector_reserved;
		parent_cluster=0;
		}
	else parent_cluster=clstr;

	Word cluster_size=boot.cluster_size*boot.sector_size;
	tmpcluster=(Byte*)malloc(cluster_size);
	if (!tmpcluster) return(MERROR_NOT_ENOGHT_MEMORY);

	bool find=false;
	Word curent_cluster=clstr;
	Word curent_position=0;
	if (!root) cluster_Read(tmpcluster,curent_cluster);
	else sector_Read(tmpcluster,curent_cluster);

	while (!find) {
		if (tmpcluster[curent_position*32]==0 || tmpcluster[curent_position*32]==229) {
			find_position=curent_position;
			find_cluster=curent_cluster;
			find=true;
			}

		curent_position++;
		if (curent_position>=cluster_size/32 && !find) { /* Если закончился кластер */
			old_curent_cluster=curent_cluster;
			if (!root) curent_cluster=FAT[curent_cluster];
			else { /* Если корень, то никакого фата */
				curent_cluster++;
				if (curent_cluster>=boot.root_size*32/boot.sector_size + boot.fat_count*boot.fat_size+boot.sector_reserved) curent_cluster=4095;
				}
			curent_position=0;
			if (curent_cluster==0 || curent_cluster>clusters_total) { /* Если нет следующего кластера в цепочке */
				if (!root) { /* Если не корень */
					curent_cluster=cluster_findfirst();
					if (curent_cluster==0) return(MERROR_NOT_ENOGHT_FREE_SPACE);
					memset(tmpcluster,0,cluster_size);
					FAT[old_curent_cluster]=curent_cluster;
					FAT[curent_cluster]=4095;
					}
				else { /* Если корень, то облом, там каталог фиксированного размера */
					return(MERROR_NOT_ENOGHT_FREE_SPACE);
					}
				}
			else {
				if (root) sector_Read(tmpcluster,curent_cluster);
				else cluster_Read(tmpcluster,curent_cluster);
				}
			}
		} /* of while */


	/* Откушаем один кластер под каталог */
	Word new_cluster=cluster_findfirst();

	if (new_cluster==0) return(MERROR_NOT_ENOGHT_FREE_SPACE);

	FAT[new_cluster]=4095;

	/* Если надо, сохраним первую копию FAT */
	if (boot.fat_count>0) write_FAT(1);

	memset(&dirent,0,sizeof(dirent));

	timer = time(NULL);
	tblock = localtime(&timer);

	file_t.sec=tblock->tm_sec/2;
	file_t.min=tblock->tm_min;
	file_t.hour=tblock->tm_hour;
	file_d.day=tblock->tm_mday;
	file_d.month=tblock->tm_mon+1;
	file_d.year=tblock->tm_year-80;

	/* Порежем имя на две части */
	Byte* ext=strchr(newdirname,46);
	i=0;
	if (ext) {
		ext[0]=0;
		ext++;
		while (ext[i]!=0 && i<3) {dirent.ext[i]=ext[i];i++;}
		}
    else memset(dirent.ext,0x20,3);
	i=0;
	while (newdirname[i]!=0 && i<8) {dirent.name[i]=newdirname[i];i++;}
    while (i<8) {dirent.name[i]=0x20;i++;}
	dirent.attr_dir=1;
	dirent.time=file_t;
	dirent.date=file_d;
	dirent.ClstrNo=new_cluster;
	dirent.filesize=0;
	memcpy(tmpcluster+find_position*32,&dirent,32);
    if (!root) cluster_Write(tmpcluster,find_cluster);
    else sector_Write(tmpcluster,find_cluster);

	// Теперь создаем пустой каталог и пишем туда ".." и "."
	memset(tmpcluster,0,cluster_size);
   	memcpy(dirent.name,"..      ",8);
   	memcpy(dirent.ext,"   ",3);
    dirent.ClstrNo=parent_cluster;
   	memcpy(tmpcluster,&dirent,32);
   	memcpy(&dirent.name,".       ",8);
   	memcpy(dirent.ext,"   ",3);
   	dirent.ClstrNo=new_cluster;
   	memcpy(tmpcluster+32,&dirent,32);
	cluster_Write(tmpcluster,new_cluster);

	/* Если надо, сохраним вторую копию FAT */
	if (boot.fat_count>1) write_FAT(2);

	free(tmpcluster);
	return(MERROR_OK);
	}

/* Создание файла ############################################################*/
int createfile(char*dirname, char* newfilename) {
	Byte *tmpcluster;
	Word find_position,find_cluster;
	DirectoryEntry dirent;
	int i;
	FileDate file_d;
	FileTime file_t;
	time_t timer;
	struct tm *tblock;
	Word old_curent_cluster;
    bool root=false;

	if (!dirname || !newfilename) return(MERROR_CREATING_FILE);
	if (newfilename[0]==0) return(MERROR_CREATING_FILE);

	Word clstr=get_Cluster(dirname);
	if (clstr==0) return(MERROR_FILE_NOT_FOUND);

    if (clstr==1) { /* Если 1-ый кластер, то это корень */
		root=true;
		clstr=boot.fat_count*boot.fat_size+boot.sector_reserved;
		}

	Word cluster_size=boot.cluster_size*boot.sector_size;
	tmpcluster=(Byte*)malloc(cluster_size);
	if (!tmpcluster) return(MERROR_NOT_ENOGHT_MEMORY);

	bool find=false;
	Word curent_cluster=clstr;
	Word curent_position=0;
	if (!root) cluster_Read(tmpcluster,curent_cluster);
	else sector_Read(tmpcluster,curent_cluster);

	while (!find) {
		if (tmpcluster[curent_position*32]==0 || tmpcluster[curent_position*32]==229) {
			find_position=curent_position;
			find_cluster=curent_cluster;
			find=true;
			}

		curent_position++;
		if (curent_position>=cluster_size/32 && !find) { /* Если закончился кластер */
			old_curent_cluster=curent_cluster;
			if (!root) curent_cluster=FAT[curent_cluster];
			else { /* Если корень, то никакого фата */
				curent_cluster++;
				if (curent_cluster>=boot.root_size*32/boot.sector_size + boot.fat_count*boot.fat_size+boot.sector_reserved) curent_cluster=4095;
				}
			curent_position=0;
			if (curent_cluster==0 || curent_cluster>clusters_total) { /* Если нет следующего кластера в цепочке */
				if (!root) { /* Если не корень */
					curent_cluster=cluster_findfirst();
					if (curent_cluster==0) return(MERROR_NOT_ENOGHT_FREE_SPACE);
					memset(tmpcluster,0,cluster_size);
					FAT[old_curent_cluster]=curent_cluster;
					FAT[curent_cluster]=4095;
					}
				else { /* Если корень, то облом, там каталог фиксированного размера */
					return(MERROR_NOT_ENOGHT_FREE_SPACE);
					}
				}
			else {
				if (root) sector_Read(tmpcluster,curent_cluster);
				else cluster_Read(tmpcluster,curent_cluster);
				}
			}
		} /* of while */


	/* Откушаем один кластер под каталог */
	Word new_cluster=cluster_findfirst();

	if (new_cluster==0) return(MERROR_NOT_ENOGHT_FREE_SPACE);

	FAT[new_cluster]=4095;

	/* Если надо, сохраним первую копию FAT */
	if (boot.fat_count>0) write_FAT(1);

	memset(&dirent,0,sizeof(dirent));

	timer = time(NULL);
	tblock = localtime(&timer);

	file_t.sec=tblock->tm_sec/2;
	file_t.min=tblock->tm_min;
	file_t.hour=tblock->tm_hour;
	file_d.day=tblock->tm_mday;
	file_d.month=tblock->tm_mon+1;
	file_d.year=tblock->tm_year-80;

	/* Порежем имя на две части */
	Byte* ext=strchr(newfilename,46);
	i=0;
	if (ext) {
		ext[0]=0;
		ext++;
		while (ext[i]!=0 && i<3) {dirent.ext[i]=ext[i];i++;}
		}
    else memset(dirent.ext,0x20,3);
	i=0;
	while (newfilename[i]!=0 && i<8) {dirent.name[i]=newfilename[i];i++;}
    while (i<8) {dirent.name[i]=0x20;i++;}
	dirent.attr_archv=1;
	dirent.time=file_t;
	dirent.date=file_d;
	dirent.ClstrNo=new_cluster;
	dirent.filesize=0;
	memcpy(tmpcluster+find_position*32,&dirent,32);
    if (!root) cluster_Write(tmpcluster,find_cluster);
    else sector_Write(tmpcluster,find_cluster);

	// Теперь обнуляем первый кластер файла
	memset(tmpcluster,0,cluster_size);
	cluster_Write(tmpcluster,new_cluster);

	/* Если надо, сохраним вторую копию FAT */
	if (boot.fat_count>1) write_FAT(2);

	free(tmpcluster);
	return(MERROR_OK);
	}

/* Добавить файл с сохранением путей #########################################*/
int addfile(char* filename) {
	Byte buff[512];
	int error;
	int k=0;
	while(filename[k]!=0) {filename[k]=rtoupper(filename[k]);k++;}

	if (!filename) return(MERROR_FILENAME_MUST_BE_SPECIFIED);
	if (filename[0]==0) return(MERROR_FILENAME_MUST_BE_SPECIFIED);

	/* Пытаемся открыть каталог, если не открывается, то это файл, иначе каталог, */
    /* и надо рекурсивно добавить все его содержимое в архив */
	DIR *dir;
	struct dirent *ent;

   	dir=opendir(filename);
	if (dir) {
		while ((ent = readdir(dir)) != NULL) {
			if (strcmp(ent->d_name,".")!=0 && strcmp(ent->d_name,"..")!=0) {
				char* newname=(char*)malloc(260);
				if (!newname) return(MERROR_NOT_ENOGHT_MEMORY);
				strcpy(newname,filename);
				strcat(newname,"\\");
				strcat(newname,ent->d_name);
				error=addfile(newname);
				if (error!=MERROR_OK) return(error);
				free(newname);
				}
			}
		closedir(dir);
		}
	else { /* Если это файл */
		printf("\nAdding file %s...",filename);
		int error;
        char fullpath[260];
		fullpath[0]=0;

		char* dfilename=strdup(filename);
		Byte *fname=strrchr(dfilename,92);
		if (fname) {
			fname[0]=0;
			fname++;

			char * pToken;
			while (dfilename != NULL) {
				pToken = strchr(dfilename,92);
				if (pToken) pToken[0]=0;

				error=createdir(fullpath,dfilename);
				if (error!=MERROR_OK && error!=MERROR_DIRECTORY_ALREADY_EXISTS) return(error);

				if (fullpath[0]!=0) strcat(fullpath,"\\");
				strcat(fullpath,dfilename);
				if (pToken) dfilename=pToken+1;
				else dfilename=NULL;
				}
			}
        else fname=filename;
    	free(dfilename);
		FILE *fp=fopen(filename,"rb");
		if (!fp) return(MERROR_FILE_NOT_FOUND);
        char *dfname=strdup(fname);
		error=createfile(fullpath,dfname);
        free(dfname);
		if (error!=MERROR_OK) return(error);
		m_FILE *fw=m_fopen(filename);
		if (!fw) {
			deletefile(filename);
			return(MERROR_CREATING_FILE);
			}
		int size;
		do {
			size=fread(&buff,1,512,fp);
			if (size!=0) {
				m_fwrite((char*)&buff,1,size,fw);
				}
		} while (size!=0);
        m_fclose(fw);
		fclose(fp);
		}

	return(MERROR_OK);
	}

/* Main ######################################################################*/
int main(int argc, char* argv[]) {
//  FILE *db=fopen("debug","at");
//	for (int i=0;i<argc;i++) {
//		fprintf(db,"%s ",argv[i]);
//		}
//	fprintf(db,"\n");
//	fclose(db);
	int error=MERROR_OK;
	bool action=false;

	if (argc==2) {
		if (strcmp(argv[1],"-r")==0) {ShowHelp(1);return(error);}
		}
	if (argc<3) ShowHelp(0);
	else {
		if (argc==3) if (strcmp(argv[1],"-c")==0) {error=createdisk(argv[2],NULL);return(error);}
		if (argc==4) if (strcmp(argv[1],"-c")==0) {error=createdisk(argv[2],argv[3]);return(error);}
		/* Открываем диск для чтения */
		disk=fopen(argv[2],"r+b");
		if (!disk) return(MERROR_FILE_NOT_FOUND);

		/* Читаем boot */
		sector=(char*)malloc(512);
		if (!sector) return(MERROR_NOT_ENOGHT_MEMORY);

		fread(sector,1,512,disk);
		memcpy(&boot,sector,sizeof(boot));
        free(sector);
		clusters_total=(boot.fat_size*boot.sector_size*2)/3;
		last_read_cluster=-1;

		/* Выделяем память */
		cluster=(char*)malloc(boot.cluster_size*boot.sector_size);
		sector=(char*)malloc(boot.sector_size);
		FAT=(Word*)malloc(boot.fat_size*boot.sector_size*sizeof(Word));
		if (!FAT || !cluster || !sector) return(MERROR_NOT_ENOGHT_MEMORY);

		/* Читаем FAT */
		read_FAT();

		/* UPCASE'им параметры */
		for (int i=3;i<argc;i++) {
			int j=0;
			while (argv[i][j]!=0) {argv[i][j]=rtoupper(argv[i][j]);j++;}
			}

		if (argc==3) { /* Один параметр */
			if (strcmp(argv[1],"-b")==0) {action=true;print_Boot();}
			if (strcmp(argv[1],"-l")==0) {action=true;dir("");}
			if (strcmp(argv[1],"-v")==0) {action=true;print_All("");}
			if (strcmp(argv[1],"-x")==0) {action=true;xextract("");}
			}
		if (argc==4) { /* Два параметра */
			if (strcmp(argv[1],"-l")==0 && strlen(argv[2])!=0) {action=true;dir(argv[3]);}
			if (strcmp(argv[1],"-e")==0 && strlen(argv[2])!=0) {action=true;extract(argv[3]);}
			if (strcmp(argv[1],"-x")==0 && strlen(argv[2])!=0) {action=true;xextract(argv[3]);}
			if (strcmp(argv[1],"-d")==0 && strlen(argv[2])!=0) {action=true;error=deletefile(argv[3]);}
			if (strcmp(argv[1],"-a")==0 && strlen(argv[2])!=0) {action=true;error=addfile(argv[3]);}
			}
		if (argc==5) { /* Три параметра */
			if (strcmp(argv[1],"-md")==0 && strlen(argv[2])!=0) {action=true;error=createdir(argv[3],argv[4]);}
			if (strcmp(argv[1],"-mf")==0 && strlen(argv[2])!=0) {action=true;error=createfile(argv[3],argv[4]);}
			}
		free(FAT);
		free(cluster);
		free(sector);
		fclose(disk);
		}
	if (!action) ShowHelp(0);
	if (error!=0) printf("Error code: %d\n",error);
	return(error);
	}
