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

📄 mkdosfs.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
   Filename:     mkdosfs.c
   Version:      0.3b (Yggdrasil)
   Author:       Dave Hudson
   Started:      24th August 1994
   Last Updated: 7th May 1998
   Updated by:   Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
   Target O/S:   Linux (2.x)

   Description: Utility to allow an MS-DOS filesystem to be created
   under Linux.  A lot of the basic structure of this program has been
   borrowed from Remy Card's "mke2fs" code.

   As far as possible the aim here is to make the "mkdosfs" command
   look almost identical to the other Linux filesystem make utilties,
   eg bad blocks are still specified as blocks, not sectors, but when
   it comes down to it, DOS is tied to the idea of a sector (512 bytes
   as a rule), and not the block.  For example the boot block does not
   occupy a full cluster.

   Fixes/additions May 1998 by Roman Hodek
   <Roman.Hodek@informatik.uni-erlangen.de>:
   - Atari format support
   - New options -A, -S, -C
   - Support for filesystems > 2GB
   - FAT32 support
   
   Port to work under Windows NT/2K/XP Dec 2002 by
   Jens-Uwe Mager <jum@anubis.han.de>

   Copying:     Copyright 1993, 1994 David Hudson (dave@humbug.demon.co.uk)

   Portions copyright 1992, 1993 Remy Card (card@masi.ibp.fr)
   and 1991 Linus Torvalds (torvalds@klaava.helsinki.fi)

   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, 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 the header files */

#include "../version.h"

#ifdef _WIN32
#define _WIN32_WINNT	0x0400
#include <windows.h>
#include <winioctl.h>
#define __LITTLE_ENDIAN	1234
#define __BIG_ENDIAN	4321
#define __BYTE_ORDER	__LITTLE_ENDIAN
#define inline
#define __attribute__(x)
#define BLOCK_SIZE		512
#else
#include <linux/hdreg.h>
#include <linux/fs.h>
#include <linux/fd.h>
#include <endian.h>
#include <mntent.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <unistd.h>
#endif
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>

#if __BYTE_ORDER == __BIG_ENDIAN

#include <asm/byteorder.h>
#ifdef __le16_to_cpu
/* ++roman: 2.1 kernel headers define these function, they're probably more
 * efficient then coding the swaps machine-independently. */
#define CF_LE_W	__le16_to_cpu
#define CF_LE_L	__le32_to_cpu
#define CT_LE_W	__cpu_to_le16
#define CT_LE_L	__cpu_to_le32
#else
#define CF_LE_W(v) ((((v) & 0xff) << 8) | (((v) >> 8) & 0xff))
#define CF_LE_L(v) (((unsigned)(v)>>24) | (((unsigned)(v)>>8)&0xff00) | \
               (((unsigned)(v)<<8)&0xff0000) | ((unsigned)(v)<<24))
#define CT_LE_W(v) CF_LE_W(v)
#define CT_LE_L(v) CF_LE_L(v)
#endif /* defined(__le16_to_cpu) */
    
#else

#define CF_LE_W(v) (v)
#define CF_LE_L(v) (v)
#define CT_LE_W(v) (v)
#define CT_LE_L(v) (v)

#endif /* __BIG_ENDIAN */

#ifdef _WIN32

typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;
typedef unsigned __int64 __u64;
typedef __int64 loff_t;
typedef __int64 ll_t;

extern char *optarg;
extern int optind;
extern int opterr;
extern int optopt;
int getopt(int argc, char *const argv[], const char * optstring);

static int is_device = 0;

#define open	WIN32open
#define close	WIN32close
#define read	WIN32read
#define write	WIN32write
#define llseek	WIN32llseek

#define O_SHORT_LIVED   _O_SHORT_LIVED
#define O_ACCMODE       3
#define O_NONE          3
#define O_BACKUP        0x10000
#define O_SHARED        0x20000

static int WIN32open(const char *path, int oflag, ...)
{
	HANDLE fh;
	DWORD desiredAccess;
	DWORD shareMode;
	DWORD creationDisposition;
	DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL;
	SECURITY_ATTRIBUTES securityAttributes;
	va_list ap;
	int pmode;
	int trunc = FALSE;

	securityAttributes.nLength = sizeof(securityAttributes);
	securityAttributes.lpSecurityDescriptor = NULL;
	securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE;
	switch (oflag & O_ACCMODE) {
	case O_RDONLY:
		desiredAccess = GENERIC_READ;
		shareMode = FILE_SHARE_READ;
		break;
	case O_WRONLY:
		desiredAccess = GENERIC_WRITE;
		shareMode = 0;
		break;
	case O_RDWR:
		desiredAccess = GENERIC_READ|GENERIC_WRITE;
		shareMode = 0;
		break;
	case O_NONE:
		desiredAccess = 0;
		shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
	}
	if (oflag & O_APPEND) {
		desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE;
		shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
	}
	if (oflag & O_SHARED)
		shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE;
        switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) {
	case 0:
	case O_EXCL:
		creationDisposition = OPEN_EXISTING;
		break;
	case O_CREAT:
		creationDisposition = OPEN_ALWAYS;
		break;
	case O_CREAT|O_EXCL:
	case O_CREAT|O_TRUNC|O_EXCL:
		creationDisposition = CREATE_NEW;
		break;
	case O_TRUNC:
	case O_TRUNC|O_EXCL:
		creationDisposition = TRUNCATE_EXISTING;
		break;
	case O_CREAT|O_TRUNC:
		creationDisposition = OPEN_ALWAYS;
		trunc = TRUE;
		break;
        }
	if (oflag & O_CREAT) {
		va_start(ap, oflag);
		pmode = va_arg(ap, int);
		va_end(ap);
		if ((pmode & 0222) == 0)
			flagsAttributes |= FILE_ATTRIBUTE_READONLY;
	}
	if (oflag & O_TEMPORARY) {
		flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
		desiredAccess |= DELETE;
	}
	if (oflag & O_SHORT_LIVED)
		flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY;
	if (oflag & O_SEQUENTIAL)
		flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
	else if (oflag & O_RANDOM)
		flagsAttributes |= FILE_FLAG_RANDOM_ACCESS;
	if (oflag & O_BACKUP)
		flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
	if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes,
				creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) {
		errno = GetLastError();
		return -1;
	}
	if (trunc) {
		if (!SetEndOfFile(fh)) {
			errno = GetLastError();
			CloseHandle(fh);
			DeleteFile(path);
			return -1;
		}
	}
	return (int)fh;
}

static int WIN32close(int fd)
{
	if (!CloseHandle((HANDLE)fd)) {
		errno = GetLastError();
		return -1;
	}
	return 0;
}

static int WIN32read(int fd, void *buf, unsigned int len)
{
	DWORD actualLen;

	if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
		errno = GetLastError();
		if (errno == ERROR_BROKEN_PIPE)
			return 0;
		else
			return -1;
	}
	return (int)actualLen;
}

static int WIN32write(int fd, void *buf, unsigned int len)
{
	DWORD actualLen;

	if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
		errno = GetLastError();
		return -1;
	}
	return (int)actualLen;
}

static loff_t WIN32llseek(int fd, loff_t offset, int whence)
{
	long lo, hi;
	DWORD err;

	lo = offset & 0xffffffff;
	hi = offset >> 32;
	lo = SetFilePointer((HANDLE)fd, lo, &hi, whence);
	if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) {
		errno = err;
		return -1;
	}
	return ((loff_t)hi << 32) | (off_t)lo;
}

int fsctl(int fd, int code)
{
	DWORD ret;
	if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) {
		errno = GetLastError();
		return -1;
	}
	return 0; 
}

#else

#define O_NOINHERIT    0
#define O_TEMPORARY    0
#define O_SHORT_LIVED  0
#define O_SEQUENTIAL   0
#define O_RANDOM       0
#define O_BACKUP       0
#define O_SHARED       0
#ifndef O_NONE
# define O_NONE        0
#endif

typedef long long ll_t;
/* Use the _llseek system call directly, because there (once?) was a bug in
 * the glibc implementation of it. */
#include <linux/unistd.h>
#if defined(__alpha) || defined(__ia64__)
/* On alpha, the syscall is simply lseek, because it's a 64 bit system. */
static loff_t llseek( int fd, loff_t offset, int whence )
{
    return lseek(fd, offset, whence);
}
#else
# ifndef __NR__llseek
# error _llseek system call not present
# endif
static _syscall5( int, _llseek, uint, fd, ulong, hi, ulong, lo,
		  loff_t *, res, uint, wh );
static loff_t llseek( int fd, loff_t offset, int whence )
{
    loff_t actual;

    if (_llseek(fd, offset>>32, offset&0xffffffff, &actual, whence) != 0)
	return (loff_t)-1;
    return actual;
}
#endif

#endif

/* Constant definitions */

#define TRUE 1			/* Boolean constants */
#define FALSE 0

#define TEST_BUFFER_BLOCKS 16
#define HARD_SECTOR_SIZE   512
#define SECTORS_PER_BLOCK ( BLOCK_SIZE / HARD_SECTOR_SIZE )


/* Macro definitions */

/* Report a failure message and return a failure error code */

#define die( str ) fatal_error( "%s: " str "\n" )


/* Mark a cluster in the FAT as bad */

#define mark_sector_bad( sector ) mark_FAT_sector( sector, FAT_BAD )

/* Compute ceil(a/b) */

inline int
cdiv (int a, int b)
{
  return (a + b - 1) / b;
}

/* MS-DOS filesystem structures -- I included them here instead of
   including linux/msdos_fs.h since that doesn't include some fields we
   need */

#define ATTR_RO      1		/* read-only */
#define ATTR_HIDDEN  2		/* hidden */
#define ATTR_SYS     4		/* system */
#define ATTR_VOLUME  8		/* volume label */
#define ATTR_DIR     16		/* directory */
#define ATTR_ARCH    32		/* archived */

#define ATTR_NONE    0		/* no attribute bits */
#define ATTR_UNUSED  (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
	/* attribute bits that are copied "as is" */

/* FAT values */
#define FAT_EOF      (atari_format ? 0x0fffffff : 0x0ffffff8)
#define FAT_BAD      0x0ffffff7

#define MSDOS_EXT_SIGN 0x29	/* extended boot sector signature */
#define MSDOS_FAT12_SIGN "FAT12   "	/* FAT12 filesystem signature */
#define MSDOS_FAT16_SIGN "FAT16   "	/* FAT16 filesystem signature */
#define MSDOS_FAT32_SIGN "FAT32   "	/* FAT32 filesystem signature */

#define BOOT_SIGN 0xAA55	/* Boot sector magic number */

#define MAX_CLUST_12	((1 << 12) - 16)
#define MAX_CLUST_16	((1 << 16) - 16)
/* M$ says the high 4 bits of a FAT32 FAT entry are reserved and don't belong
 * to the cluster number. So the max. cluster# is based on 2^28 */
#define MAX_CLUST_32	((1 << 28) - 16)

#define FAT12_THRESHOLD	4078

#define OLDGEMDOS_MAX_SECTORS	32765
#define GEMDOS_MAX_SECTORS	65531
#define GEMDOS_MAX_SECTOR_SIZE	(16*1024)

#define BOOTCODE_SIZE		448
#define BOOTCODE_FAT32_SIZE	420

/* __attribute__ ((packed)) is used on all structures to make gcc ignore any
 * alignments */

#ifdef _WIN32
#pragma pack(push, 1)
#endif
struct msdos_volume_info {
  __u8		drive_number;	/* BIOS drive number */
  __u8		RESERVED;	/* Unused */
  __u8		ext_boot_sign;	/* 0x29 if fields below exist (DOS 3.3+) */
  __u8		volume_id[4];	/* Volume ID number */
  __u8		volume_label[11];/* Volume label */
  __u8		fs_type[8];	/* Typically FAT12 or FAT16 */

⌨️ 快捷键说明

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