blob: ccd44800aa952a1463235cc2696d3689c5ecc071 [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 Marshallecb52062019-01-15 10:07:29 -080022#include "sgdisk.h"
Tom Marshall7b5b7112019-07-23 15:18:15 -070023#include "gptcl.h"
Tom Marshallecb52062019-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 Marshallecb52062019-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 Marshallecb52062019-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 Marshallecb52062019-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 Marshallecb52062019-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;
63 case gpt:
64 gptData.JustLooking();
65 if (!gptData.LoadPartitions((string) device)) {
66 cerr << "Failed to read GPT" << endl;
67 return 9;
68 }
69
Tom Marshallecb52062019-01-15 10:07:29 -080070 ptbl.type = GPT;
71 ptbl.guid = gptData.GetDiskGUID().AsString();
72 for (size_t i = 0; i < gptData.GetNumParts(); i++) {
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080073 partData = gptData[i];
74 if (partData.GetFirstLBA() > 0) {
Tom Marshallecb52062019-01-15 10:07:29 -080075 sgdisk_partition part;
76 part.num = i + 1;
77 part.type = partData.GetType().AsString();
78 part.guid = partData.GetUniqueGUID().AsString();
79 part.name = partData.GetDescription();
80 partitions.push_back(part);
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080081 }
82 }
83 break;
84 default:
85 cerr << "Unknown partition table" << endl;
86 return 10;
87 }
88
Tom Marshallecb52062019-01-15 10:07:29 -080089 fflush(stdout);
90 fflush(stderr);
91 dup2(stdout_fd, STDOUT_FILENO);
92 dup2(stderr_fd, STDERR_FILENO);
93 close(silence);
94
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -080095 return 0;
96}
97
Tom Marshallecb52062019-01-15 10:07:29 -080098/*
99 * Dump partition details in a machine readable format:
100 *
101 * DISK [mbr|gpt] [guid]
102 * PART [n] [type] [guid]
103 */
104static int android_dump(const char* device) {
105 sgdisk_partition_table ptbl;
106 vector<sgdisk_partition> partitions;
107 int rc = sgdisk_read(device, ptbl, partitions);
108 if (rc == 0) {
109 stringstream res;
110 switch (ptbl.type) {
111 case MBR:
112 res << "DISK mbr" << endl;
113 for (auto& part : partitions) {
114 res << "PART " << part.num << " " << part.type << endl;
115 }
116 break;
117 case GPT:
118 res << "DISK gpt " << ptbl.guid << endl;
119 for (auto& part : partitions) {
120 res << "PART " << part.num << " " << part.type << " "
121 << part.guid << " " << part.name << endl;
122 }
123 break;
124 default:
125 return 10;
126 }
127 string partStr = res.str();
128 write(STDOUT_FILENO, partStr.c_str(), partStr.length());
129 }
130 return rc;
131}
132
Tom Marshall401464e2015-11-04 15:48:02 -0800133extern "C" int main(int argc, char *argv[]) {
Jeff Sharkeyd4e73c92015-02-28 20:21:52 -0800134 for (int i = 0; i < argc; i++) {
135 if (!strcmp("--android-dump", argv[i])) {
136 return android_dump(argv[i + 1]);
137 }
138 }
139
140 GPTDataCL theGPT;
141 return theGPT.DoOptions(argc, argv);
142}