📄 fdisk.c
字号:
//// Visopsys// Copyright (C) 1998-2007 J. Andrew McLaughlin// // 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.,// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// fdisk.c//// This is a program for modifying partition tables and doing other disk// management tasks./* This is the text that appears when a user requests help about this program<help> -- fdisk --Also known as the "Disk Manager", fdisk is a hard disk partitioning tool.It can create, delete, format, resize, and move partitions and modify theirattributes. It can copy entire hard disks from one to another.Usage: fdisk [-T] [-o] [disk_name]The fdisk program is interactive, and can be used in either text or graphicsmode. It provides the same functionality in both modes; text mode operationis menu-driven.The disk can be automatically selected by specifying its name (as listed bythe 'disks' command) as the last argument.Options:-T : Force text mode operation-o <disk_name> : Clear the partition table of the specified diskDevelopment of this program is ongoing and will be a major focus ofimprovements in future releases, aiming towards providing much of the samefunctionality of PartitionMagic and similar utilities.</help>*/#include "fdisk.h"#include "msdos.h"#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/api.h>#include <sys/fat.h>#include <sys/ntfs.h>#include <sys/vsh.h>#define PERM "You must be a privileged user to use this " \ "command.\n(Try logging in as user \"admin\")"#define PARTTYPES "Supported Partition Types"#define STARTCYL_MESSAGE "Enter starting cylinder (%u-%u)"#define ENDCYL_MESSAGE "Enter ending cylinder (%u-%u)\n" \ "or size in megabytes with 'm' (1m-%um),\n" \ "or size in cylinders with 'c' (1c-%uc)"static const char *programName = NULL;static int processId = 0;static int readOnly = 1;static diskLabel *msdosLabel = NULL;static int numberDisks = 0;static disk *disks = NULL;partitionTable *table = NULL;static textScreen screen;static char *tmpBackupName = NULL;static char sliceListHeader[SLICESTRING_LENGTH + 1];static listItemParameters *diskListParams = NULL;static ioThreadArgs readerArgs;static ioThreadArgs writerArgs;static int ioThreadsTerminate = 0;static int ioThreadsFinished = 0;static int checkTableAsk = 1;static slice clipboardSlice;static disk *clipboardDisk = NULL;static int clipboardSliceValid = 0;// GUI stuffstatic int graphics = 0;static objectKey window = NULL;static objectKey fileMenu = NULL;static objectKey diskMenu = NULL;static objectKey partMenu = NULL;static objectKey diskList = NULL;static objectKey canvas = NULL;static objectKey sliceList = NULL;static objectKey writeButton = NULL;static objectKey undoButton = NULL;static objectKey defragButton = NULL;static objectKey setActiveButton = NULL;static objectKey deleteButton = NULL;static objectKey deleteAllButton = NULL;static objectKey formatButton = NULL;static objectKey hideButton = NULL;static objectKey infoButton = NULL;static objectKey moveButton = NULL;static objectKey newButton = NULL;static objectKey resizeButton = NULL;static unsigned canvasWidth = 600;static unsigned canvasHeight = 60;// Menus#define FILEMENU_WRITE 0#define FILEMENU_UNDO 1#define FILEMENU_RESTOREBACKUP 2#define FILEMENU_QUIT 3windowMenuContents fileMenuContents = { 4, { { "Write", NULL }, { "Undo", NULL }, { "Restore backup", NULL }, { "Quit", NULL } }};#define DISKMENU_COPYDISK 0#define DISKMENU_PARTORDER 1#define DISKMENU_SIMPLEMBR 2#define DISKMENU_BOOTMENU 3#define DISKMENU_ERASEDISK 4windowMenuContents diskMenuContents = { 5, { { "Copy disk", NULL }, { "Partition order", NULL }, { "Write basic MBR", NULL }, { "MBR boot menu", NULL }, { "Erase disk", NULL } }}; #define PARTMENU_COPY 0#define PARTMENU_PASTE 1#define PARTMENU_SETACTIVE 2#define PARTMENU_DELETE 3#define PARTMENU_FORMAT 4#define PARTMENU_DEFRAG 5#define PARTMENU_RESIZE 6#define PARTMENU_HIDE 7#define PARTMENU_INFO 8#define PARTMENU_LISTTYPES 9#define PARTMENU_MOVE 10#define PARTMENU_CREATE 11#define PARTMENU_DELETEALL 12#define PARTMENU_SETTYPE 13#define PARTMENU_ERASE 14windowMenuContents partMenuContents = { 15, { { "Copy", NULL }, { "Paste", NULL }, { "Set active", NULL }, { "Delete", NULL }, { "Format", NULL }, { "Defragment", NULL }, { "Resize", NULL }, { "Hide/Unhide", NULL }, { "Info", NULL }, { "List types", NULL }, { "Move", NULL }, { "Create", NULL }, { "Delete all", NULL }, { "Set type", NULL }, { "Erase", NULL } }};static int yesOrNo(char *question){ char character; if (graphics) return (windowNewQueryDialog(window, "Confirmation", question)); else { printf("\n%s (y/n): ", question); textInputSetEcho(0); while(1) { character = getchar(); if ((character == 'y') || (character == 'Y')) { printf("Yes\n"); textInputSetEcho(1); return (1); } else if ((character == 'n') || (character == 'N')) { printf("No\n"); textInputSetEcho(1); return (0); } } }}static void quit(int status, int force){ // Shut everything down if (!force && table->changesPending && !yesOrNo("Quit without writing changes?")) return; if (graphics) { windowGuiStop(); if (window) windowDestroy(window); } else { if (screen.data) textScreenRestore(&screen); } if (tmpBackupName) { fileDelete(tmpBackupName); tmpBackupName = NULL; } // Free any malloc'ed global memory if (screen.data) memoryRelease(screen.data); if (disks) free(disks); if (diskListParams) free(diskListParams); if (table) free(table); exit(errno = status);}static int getNumberDialog(const char *title, const char *prompt){ // Creates a dialog that prompts for a number value int status = 0; char buffer[11]; status = windowNewPromptDialog(window, title, prompt, 1, 10, buffer); if (status < 0) return (status); if (buffer[0] == '\0') return (status = ERR_NODATA); // Try to turn it into a number buffer[10] = '\0'; status = atoi(buffer); return (status);}static char readKey(const char *choices, int allowCursor){ int stringLength = strlen(choices); char character; int count; textInputSetEcho(0); while(1) { character = getchar(); if (allowCursor && ((character == (unsigned char) 17) || (character == (unsigned char) 20))) return (character); for (count = 0; count < stringLength; count ++) if (character == choices[count]) { printf("%c\n", character); textInputSetEcho(1); return (character); } }}static int readLine(const char *choices, char *buffer, int length){ int choicesLength = strlen(choices); int count1, count2; textInputSetEcho(0); for (count1 = 0; count1 < (length - 1); count1 ++) { buffer[count1] = getchar(); if (buffer[count1] == 10) // Newline { buffer[count1] = '\0'; break; } if (buffer[count1] == 8) // Backspace { if (count1 > 0) { textBackSpace(); count1 -= 2; } else count1 -= 1; continue; } for (count2 = 0; count2 < choicesLength; count2 ++) if (buffer[count1] == choices[count2]) { printf("%c", buffer[count1]); break; } if (buffer[count1] != choices[count2]) count1--; } // Make sure there's a NULL at the end of buffer. buffer[length - 1] = '\0'; textInputSetEcho(1); printf("\n"); return (0);}void pause(void){ printf("\nPress any key to continue. "); getchar(); printf("\n");}void error(const char *format, ...){ // Generic error message code for either text or graphics modes va_list list; char *output = NULL; output = malloc(MAXSTRINGLENGTH); if (output == NULL) return; va_start(list, format); vsnprintf(output, MAXSTRINGLENGTH, format, list); va_end(list); if (graphics) windowNewErrorDialog(window, "Error", output); else { printf("\n\n%s\n", output); pause(); } free(output);}void warning(const char *format, ...){ // Generic error message code for either text or graphics modes va_list list; char *output = NULL; output = malloc(MAXSTRINGLENGTH); if (output == NULL) return; va_start(list, format); vsnprintf(output, MAXSTRINGLENGTH, format, list); va_end(list); if (graphics) windowNewErrorDialog(window, "Warning", output); else { printf("\n\nWARNING: %s\n", output); pause(); } free(output);}static inline unsigned cylsToMb(disk *theDisk, unsigned cylinders){ unsigned tmpDiskSize = ((cylinders * CYLSECTS(theDisk)) / (1048576 / theDisk->sectorSize)); return (max(1, tmpDiskSize));}static inline unsigned mbToCyls(disk *theDisk, unsigned megabytes){ unsigned sectors = ((1048576 / theDisk->sectorSize) * megabytes); unsigned cylinders = (sectors / CYLSECTS(theDisk)); if (sectors % CYLSECTS(theDisk)) cylinders += 1; return (cylinders);}static int scanDisks(void){ int status = 0; int tmpNumberDisks = 0; disk *tmpDiskInfo = NULL; int count; // Call the kernel to give us the number of available disks tmpNumberDisks = diskGetPhysicalCount(); if (tmpNumberDisks <= 0) return (status = ERR_NOSUCHENTRY); tmpDiskInfo = malloc(DISK_MAXDEVICES * sizeof(disk)); if (tmpDiskInfo == NULL) return (status = ERR_MEMORY); // Read disk info into our temporary structure status = diskGetAllPhysical(tmpDiskInfo, (DISK_MAXDEVICES * sizeof(disk))); if (status < 0) { // Eek. Problem getting disk info. free(tmpDiskInfo); return (status); } diskListParams = malloc(DISK_MAXDEVICES * sizeof(listItemParameters)); if (diskListParams == NULL) { free(tmpDiskInfo); return (status = ERR_MEMORY); } // Loop through these disks, figuring out which ones are hard disks // and putting them into the regular array for (count = 0; count < tmpNumberDisks; count ++) if (tmpDiskInfo[count].type & DISKTYPE_HARDDISK) { memcpy(&disks[numberDisks], &tmpDiskInfo[count], sizeof(disk)); snprintf(diskListParams[numberDisks].text, WINDOW_MAX_LABEL_LENGTH, "Disk %d: [%s] %u Mb, %u cyls, %u heads, %u secs/cyl, " "%u bytes/sec", numberDisks, disks[numberDisks].name, (disks[numberDisks].numSectors / (1048576 / disks[numberDisks].sectorSize)), disks[numberDisks].cylinders, disks[numberDisks].heads, disks[numberDisks].sectorsPerCylinder, disks[numberDisks].sectorSize); numberDisks += 1; } free(tmpDiskInfo); if (numberDisks <= 0) return (status = ERR_NOSUCHENTRY); else return (status = 0);}static int checkTable(partitionTable *t, int fix){ // Does a series of correctness checks on the table, and outputs warnings // for any problems it finds slice *checkSlice = NULL; int errors = 0; unsigned endLogical = 0; unsigned expectCylinder = 0; unsigned expectHead = 0; unsigned expectSector = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -