blob: d3524c5e41868567ee58bc7f696e286d834ec434 [file] [log] [blame]
srs56941e093722010-01-05 00:14:19 -05001// sgdisk.cc
srs569473ba4792010-01-12 18:18:17 -05002// Command-line-based version of gdisk. This program is named after sfdisk,
3// and it can serve a similar role (easily scripted, etc.), but it's used
4// strictly via command-line arguments, and it doesn't bear much resemblance
5// to sfdisk in actual use.
srs56941e093722010-01-05 00:14:19 -05006//
srs569473ba4792010-01-12 18:18:17 -05007// by Rod Smith, project began February 2009; sgdisk begun January 2010.
srs56941e093722010-01-05 00:14:19 -05008
srs569464cbd172011-03-01 22:03:54 -05009/* This program is copyright (c) 2009-2011 by Roderick W. Smith. It is distributed
srs56941e093722010-01-05 00:14:19 -050010 under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
11
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080012#include <iostream>
13#include <fstream>
14#include <string.h>
15#include <string>
16#include <iostream>
17#include <sstream>
18#include <errno.h>
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080019#include <fcntl.h>
Dan Albert8fc83652015-08-12 15:52:37 -070020#include <unistd.h>
srs569473ba4792010-01-12 18:18:17 -050021
Tom Marshall2e8e0552019-01-15 10:07:29 -080022#include "sgdisk.h"
Tom Marshallbb7250f2019-07-23 15:18:15 -070023#include "gptcl.h"
Tom Marshall2e8e0552019-01-15 10:07:29 -080024
srs569473ba4792010-01-12 18:18:17 -050025using namespace std;
srs56941e093722010-01-05 00:14:19 -050026
27#define MAX_OPTIONS 50
28
Tom Marshall2e8e0552019-01-15 10:07:29 -080029int sgdisk_read(const char* device, sgdisk_partition_table& ptbl,
30 vector<sgdisk_partition>& partitions) {
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080031 BasicMBRData mbrData;
32 GPTData gptData;
33 GPTPart partData;
34 int numParts = 0;
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080035
36 /* Silence noisy underlying library */
Tom Marshall2e8e0552019-01-15 10:07:29 -080037 int stdout_fd = dup(STDOUT_FILENO);
38 int stderr_fd = dup(STDERR_FILENO);
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080039 int silence = open("/dev/null", 0);
40 dup2(silence, STDOUT_FILENO);
41 dup2(silence, STDERR_FILENO);
42
43 if (!mbrData.ReadMBRData((string) device)) {
44 cerr << "Failed to read MBR" << endl;
45 return 8;
46 }
47
48 switch (mbrData.GetValidity()) {
49 case mbr:
Tom Marshall2e8e0552019-01-15 10:07:29 -080050 ptbl.type = MBR;
51 ptbl.guid.clear();
52 for (size_t i = 0; i < MAX_MBR_PARTS; i++) {
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080053 if (mbrData.GetLength(i) > 0) {
Tom Marshall2e8e0552019-01-15 10:07:29 -080054 char typebuf[2+8+1];
55 sprintf(typebuf, "%x", (unsigned int)mbrData.GetType(i));
56 sgdisk_partition part;
57 part.num = i + 1;
58 part.type = typebuf;
59 partitions.push_back(part);
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080060 }
61 }
62 break;
3l H4ck3r C0mf0r720a492d2021-10-10 15:27:53 -030063 case hybrid:
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080064 case gpt:
65 gptData.JustLooking();
66 if (!gptData.LoadPartitions((string) device)) {
67 cerr << "Failed to read GPT" << endl;
68 return 9;
69 }
70
Tom Marshall2e8e0552019-01-15 10:07:29 -080071 ptbl.type = GPT;
72 ptbl.guid = gptData.GetDiskGUID().AsString();
73 for (size_t i = 0; i < gptData.GetNumParts(); i++) {
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080074 partData = gptData[i];
75 if (partData.GetFirstLBA() > 0) {
Tom Marshall2e8e0552019-01-15 10:07:29 -080076 sgdisk_partition part;
77 part.num = i + 1;
78 part.type = partData.GetType().AsString();
79 part.guid = partData.GetUniqueGUID().AsString();
80 part.name = partData.GetDescription();
81 partitions.push_back(part);
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080082 }
83 }
84 break;
85 default:
86 cerr << "Unknown partition table" << endl;
87 return 10;
88 }
89
Tom Marshall2e8e0552019-01-15 10:07:29 -080090 fflush(stdout);
91 fflush(stderr);
92 dup2(stdout_fd, STDOUT_FILENO);
93 dup2(stderr_fd, STDERR_FILENO);
94 close(silence);
95
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080096 return 0;
97}
98
Tom Marshall2e8e0552019-01-15 10:07:29 -080099/*
100 * Dump partition details in a machine readable format:
101 *
102 * DISK [mbr|gpt] [guid]
103 * PART [n] [type] [guid]
104 */
105static int android_dump(const char* device) {
106 sgdisk_partition_table ptbl;
107 vector<sgdisk_partition> partitions;
108 int rc = sgdisk_read(device, ptbl, partitions);
109 if (rc == 0) {
110 stringstream res;
111 switch (ptbl.type) {
112 case MBR:
113 res << "DISK mbr" << endl;
114 for (auto& part : partitions) {
115 res << "PART " << part.num << " " << part.type << endl;
116 }
117 break;
118 case GPT:
119 res << "DISK gpt " << ptbl.guid << endl;
120 for (auto& part : partitions) {
121 res << "PART " << part.num << " " << part.type << " "
122 << part.guid << " " << part.name << endl;
123 }
124 break;
125 default:
126 return 10;
127 }
128 string partStr = res.str();
129 write(STDOUT_FILENO, partStr.c_str(), partStr.length());
130 }
131 return rc;
132}
133
Tom Marshall25b8b162015-11-04 15:48:02 -0800134extern "C" int main(int argc, char *argv[]) {
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -0800135 for (int i = 0; i < argc; i++) {
136 if (!strcmp("--android-dump", argv[i])) {
137 return android_dump(argv[i + 1]);
138 }
139 }
140
141 GPTDataCL theGPT;
142 return theGPT.DoOptions(argc, argv);
143}