⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkxsfs.c

📁 一个操作系统,用C语言实现开发的,我在一个浙江大学的操作系统实验网站找到.大家学习以下
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include <memory.h>
#include <xsfs.h>
#include <xsfsstream.h>
#include <xsfstree.h>

#define MAX_NAME	80
// global variables
char sz_bootsect[MAX_NAME] = "bootsect.bin";
char sz_loader[MAX_NAME] = "loader.bin";
char sz_signature[9] = "XSFS    ";
char sz_device[MAX_NAME] = "";
int n_scale = 0;	// 0 indicates auto

// for image output
int n_image = 0;
int n_sector_size = 512;

#define F_VERBOSE	0x8000
#define F_COMPACT	0x0001
int n_flags = 0;	// flags

XSFSDESC xsfs_desc;

// public functions
void  LoadBinary(void);			// prepare device and buffer
void* GetBuffer(void);			// get buffer, buffer is the same size as sector
int   BinWrite(int pos);		// flush buffer to sector
void  FormatBinary(void);
void  Cleanup(int errcode);		// clean up, errcode = 0 indicates success

static int sw_help(char *argv[])
{
	puts("Format Utility for XSFS\n"
	     "The designing version, by EaseWay\n\n"
		 "Usage: mkxsfs [switches] device\n"
		 "Switches:\n"
		 "   -n --scale n_scale		specify scale fact\n"
		 "                          scale fact is number of sectors in one logical unit\n"
		 "	 -b --bootsect file		specify boot sector image (default bootsect.bin)\n"
		 "	 -l --loader file		specify loader image (default loader.bin)\n"
		 "   -s --signature text	specify XSFS signature (default XSFS)\n"
		 "   -c --compact-loader	set reserved sectors by loader size\n"
		 "   -m --image sectors		output to an image (device is filename)\n"
		 "   -t --sector-size size	specify sector size (only used with -m --image)\n"
		 "   -h --help              display this help\n"
		 "   -v --verbose           display details while operation is going on\n\n"
		 "For any technical supports or bug reports, please contact easeway@163.com");
	return 1;
}

static int cvt_int(const char *str)
{
	const char *p;
	for(p = str; *p; p++)
		if(*p<'0' || *p>'9') return -1;
	return atoi(str);
}

static int sw_scale(char *argv[])
{
	n_scale = cvt_int(argv[1]);
	if(n_scale<0)
	{ printf("Invalid scale fact %s\n", argv[1]); return 1; }
	return 0;
}

static int sw_bootsect(char *argv[])
{
	strncpy(sz_bootsect, argv[1], MAX_NAME-1);
	sz_bootsect[MAX_NAME-1] = 0;
	return 0;
}

static int sw_loader(char *argv[])
{
	strncpy(sz_loader, argv[1], MAX_NAME-1);
	sz_loader[MAX_NAME-1] = 0;
	return 0;
}

static int sw_signature(char *argv[])
{
	int i, l = strlen(argv[1]);
	strncpy(sz_signature, argv[1], 8);
	sz_signature[8]=0;
	if(l<8) for(i=l; i<8; i++) sz_signature[i]=' ';
	return 0;
}

static int sw_verbose(char *argv[])
{
	n_flags|=F_VERBOSE;
	return 0;
}

static int sw_compact(char *argv[])
{
	n_flags|=F_COMPACT;
	return 0;
}

static int sw_image(char *argv[])
{
	n_image = cvt_int(argv[1]);
	if(n_image<0)
	{ printf("Invalid sector number %s\n", argv[1]); return 1; }
	if(n_image<128)
	{ printf("Sector number must not be less than 128\n"); return 1; }
	return 0;
}

static int sw_sector_size(char *argv[])
{
	n_sector_size = cvt_int(argv[1]);
	if(n_sector_size<=0)
	{ printf("Invalid sector size %s\n", argv[1]); return 1; }	
	return 0;
}

static struct { char name[MAX_NAME]; int argc; int (*pfn)(char *[]); }
def_switches[] = {
	{ "-n", 1, sw_scale },
	{ "--scale", 1, sw_scale },
	{ "-b", 1, sw_bootsect },
	{ "--bootsect", 1, sw_bootsect },
	{ "-l", 1, sw_loader },
	{ "--loader", 1, sw_loader },
	{ "-s", 1, sw_signature },
	{ "--signature", 1, sw_signature },
	{ "-c", 0, sw_compact },
	{ "--compact-loader", 0, sw_compact },
	{ "-m", 1, sw_image },
	{ "--image", 1, sw_image },
	{ "-t", 1, sw_sector_size },
	{ "--sector-size", 1, sw_sector_size },
	{ "-h", 0, sw_help },
	{ "--help", 0, sw_help },
	{ "-v", 0, sw_verbose },
	{ "--verbose", 0, sw_verbose },
	{ "", 0, NULL }
};

static int find_switch_proc(const char *arg)
{
	int i;
	for(i=0; def_switches[i].pfn; i++)
		if(strcmp(def_switches[i].name, arg)==0) 
			return i;
	return -1;
}

int main(int argc, char *argv[])
{
	int i;
	
	for(i=1; i<argc; i++)
	{
		if(*argv[i]=='-')	// switches
		{
			int r, entry = find_switch_proc(argv[i]);
			if(entry<0)
			{ printf("Unknown switch %s\n", argv[i]); return 1; }
			if(argc-i-1<def_switches[entry].argc)
			{ printf("Too few arguments for %s\n", argv[i]); return 1; }
			r = def_switches[entry].pfn(&argv[i]);
			if(r!=0) return r;
			i+=def_switches[entry].argc;
		}
		else	// treat as device name
		{
			if(sz_device[0])	// device already specified
			{
				printf("You have already specified a device %s\n", sz_device);
				return 1;
			}
			else
			{
				strncpy(sz_device, argv[i], MAX_NAME-1);
				sz_device[MAX_NAME-1] = 0;
			}
		}
	}
	
	if(!sz_device[0])	// if device not specified
	{
		printf("Device not specified\n"
			   "For help type --help or -h for short\n");
		return 1;
	}

	LoadBinary();
	FormatBinary();
	Cleanup(0);
	
	return 0;	
}

static void fb_system_streams(void)
{
	XSFSSTREAM *pStream = (XSFSSTREAM*)GetBuffer();
	memset(pStream, 0, xsfs_desc.sector_size);
	
	pStream[SSI_BITMAPHASH].pri_index[0] = xsfs_desc.n_bitmap;
	pStream[SSI_FSTREE].pri_index[0] = xsfs_desc.n_bitmap+1;
	
	BinWrite(xsfs_desc.n_reserved);	
}

void fb_allocate_bitmap(void)
{
	int i, n = xsfs_desc.n_bitmap+2;	// 2 means SSI_BITMAPHASH and SSI_FSTREE
	void *buf = GetBuffer();
	_u32 *pVal = (_u32*)buf;
	memset(pVal, 0, xsfs_desc.sector_size);
	for(i=0; i<n/32; i++)
	{ *pVal = (_u32)-1; pVal ++; }
	n %= 32; *pVal = (1<<n) - 1;
	BinWrite(xsfs_desc.n_reserved+xsfs_desc.n_ss_desc);
	
	// clear left sectors in unit
	for(i=1; i<xsfs_desc.n_bitmap*xsfs_desc.n_scale; i++)
	{
		memset(buf, 0, xsfs_desc.sector_size);
		BinWrite(xsfs_desc.n_reserved+xsfs_desc.n_ss_desc+i);
	}
}

void fb_bitmap_hash(void)
{
}

void fb_fstree_root(void)
{
	XSFSROOT *root = (XSFSROOT*)GetBuffer();

	memset(root, 0, xsfs_desc.sector_size);
	root->block_size = DEF_BLOCKSIZE;
	root->free_start = 0;
	root->n_blocks = 1;
	root->n_streams = (root->block_size-sizeof(FSTBLOCK)-sizeof(FSTBLOCKDEF))/(2*sizeof(_u32));
	root->start_pos = sizeof(XSFSROOT);

	BinWrite(xsfs_desc.n_reserved+xsfs_desc.n_ss_desc+(xsfs_desc.n_bitmap+1)*xsfs_desc.n_scale);
}

void FormatBinary(void)
{
	fb_system_streams();
	fb_allocate_bitmap();
	fb_bitmap_hash();
	fb_fstree_root();
}

static void update_basic_xsfs_desc(void)
{
	xsfs_desc.version = 0;	// this can be changed as this one being updated
	xsfs_desc.sector_size = n_sector_size;
	xsfs_desc.n_scale = n_scale;
	xsfs_desc.n_sectors = n_image;
	xsfs_desc.n_units = 0;	// should be auto-detected
	xsfs_desc.n_reserved = 64;	// maximized reserved sectors
	xsfs_desc.n_ss_desc = 1;
	xsfs_desc.n_bitmap = 0;	// should be re-calculated
}

// calculate n_scale and n_units
static void default_units(void)
{
	_u32 size;
	
	if(xsfs_desc.n_scale==0)	// auto generate scale fact
		xsfs_desc.n_scale = (_u16)(xsfs_desc.n_sectors/0x01000000) + 1;
	// generally under 16M(8G) 512 bytes per unit is standable
	// that will make bitmap as large as 2M
	
	xsfs_desc.n_units = (xsfs_desc.n_sectors-xsfs_desc.n_reserved-xsfs_desc.n_ss_desc)
							/ xsfs_desc.n_scale;
	size = (_u32)xsfs_desc.sector_size * xsfs_desc.n_scale * 8;
	xsfs_desc.n_bitmap = (_u16)(xsfs_desc.n_units / size + (xsfs_desc.n_units%size?1:0));
}

FILE *fp_bs, *fp_loader;
static void load_files(void)
{
	long len;

	if(!(fp_bs = fopen(sz_bootsect, "rb")))
	{ printf("Open bootsect %s failed\n", sz_bootsect); exit(2); }	
	if(!(fp_loader = fopen(sz_loader, "rb")))
	{ fclose(fp_loader); printf("Open loader %s failed\n", sz_loader); exit(2); }	
	
	len = filelength(fileno(fp_loader));
	if(len/xsfs_desc.sector_size>=xsfs_desc.n_reserved)
	{ fclose(fp_bs); fclose(fp_loader); printf("Loader is too large\n"); exit(2); }

	if(n_flags&F_COMPACT)
		xsfs_desc.n_reserved = (_u16)(len/xsfs_desc.sector_size + (len%xsfs_desc.sector_size?1:0)) + 1;
}

// following code is platform-dependent
#if defined(DJGPP)	// MS-DOS environment


#elif defined(_MSC_VER)	// MS Visual C++

FILE *fp_binary;
void *p_buffer;

void LoadBinary(void)
{
	update_basic_xsfs_desc();
	
	load_files();
	
	fp_binary = fopen(sz_device, n_image ? "wb" : "r+b");
	if(!fp_binary)
	{
		fclose(fp_bs); fclose(fp_loader);
		printf("Open device %s failed\n", sz_device); 
		exit(2); 
	}
	
	if(n_image==0)	// no image is used, sector number should be obtained
	{
		long len = filelength(fileno(fp_binary));
		xsfs_desc.n_sectors = (_u32)(len / xsfs_desc.sector_size);
		if(xsfs_desc.n_sectors<128)
		{ printf("Device is too small (less than 128 sectors)\n"); exit(2); }
	}
	
	default_units();

	if(!(p_buffer = malloc(xsfs_desc.sector_size)))
	{
		fclose(fp_bs); fclose(fp_loader); fclose(fp_binary);
		printf("Memory %u bytes required\n", xsfs_desc.sector_size);
		exit(2);
	}
}

void *GetBuffer(void)
{ return p_buffer; }

int BinWrite(int pos)
{
	fseek(fp_binary, pos*xsfs_desc.sector_size, SEEK_SET);
	fwrite(p_buffer, xsfs_desc.sector_size, 1, fp_binary);
	return 1;
}

void Cleanup(int errcode)
{
	if(errcode==0)	// OK, all are right
	{
		int i, l;
		
		// save boot sector
		fread(p_buffer, xsfs_desc.sector_size, 1, fp_bs);
		// signature
		memcpy((char*)p_buffer+3, sz_signature, 9);
		// descriptor
		memcpy((char*)p_buffer+12, &xsfs_desc, sizeof(xsfs_desc));
		// write back
		BinWrite(0);
		
		// save loader
		for(i=0; i<xsfs_desc.n_reserved-1; i++)		
		{
			l = fread(p_buffer, xsfs_desc.sector_size, 1, fp_loader);
			if(l<=0) break;
			BinWrite(i+1);
		}
	}
	fclose(fp_bs); fclose(fp_loader); fclose(fp_binary);
	free(p_buffer);
	if(errcode!=0) exit(errcode);
}

#elif defined(__GNUC__)	// Linux


#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -