xref: /aosp_15_r20/external/gptfdisk/attributes.cc (revision 57696d54d05c64fd1b1787f8371dbcf104911cfb)
1*57696d54SAkhilesh Sanikop // attributes.cc
2*57696d54SAkhilesh Sanikop // Class to manage partition attribute codes. These are binary bit fields,
3*57696d54SAkhilesh Sanikop // of which only four are currently (2/2011) documented on Wikipedia, and
4*57696d54SAkhilesh Sanikop // two others found from other sources.
5*57696d54SAkhilesh Sanikop 
6*57696d54SAkhilesh Sanikop /* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed
7*57696d54SAkhilesh Sanikop   under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
8*57696d54SAkhilesh Sanikop 
9*57696d54SAkhilesh Sanikop #define __STDC_LIMIT_MACROS
10*57696d54SAkhilesh Sanikop #define __STDC_CONSTANT_MACROS
11*57696d54SAkhilesh Sanikop 
12*57696d54SAkhilesh Sanikop #include <stdint.h>
13*57696d54SAkhilesh Sanikop #include <stdio.h>
14*57696d54SAkhilesh Sanikop #include <iostream>
15*57696d54SAkhilesh Sanikop #include <sstream>
16*57696d54SAkhilesh Sanikop 
17*57696d54SAkhilesh Sanikop #include "attributes.h"
18*57696d54SAkhilesh Sanikop #include "support.h"
19*57696d54SAkhilesh Sanikop 
20*57696d54SAkhilesh Sanikop using namespace std;
21*57696d54SAkhilesh Sanikop 
22*57696d54SAkhilesh Sanikop string Attributes::atNames[NUM_ATR];
23*57696d54SAkhilesh Sanikop int Attributes::numAttrs = 0;
24*57696d54SAkhilesh Sanikop //Attributes::staticInit Attributes::staticInitializer;
25*57696d54SAkhilesh Sanikop 
26*57696d54SAkhilesh Sanikop // Default constructor
Attributes(void)27*57696d54SAkhilesh Sanikop Attributes::Attributes(void) {
28*57696d54SAkhilesh Sanikop    numAttrs++;
29*57696d54SAkhilesh Sanikop    if (numAttrs == 1)
30*57696d54SAkhilesh Sanikop       Setup();
31*57696d54SAkhilesh Sanikop    attributes = 0;
32*57696d54SAkhilesh Sanikop } // constructor
33*57696d54SAkhilesh Sanikop 
34*57696d54SAkhilesh Sanikop // Alternate constructor
Attributes(const uint64_t a)35*57696d54SAkhilesh Sanikop Attributes::Attributes(const uint64_t a) {
36*57696d54SAkhilesh Sanikop    numAttrs++;
37*57696d54SAkhilesh Sanikop    if (numAttrs == 1)
38*57696d54SAkhilesh Sanikop       Setup();
39*57696d54SAkhilesh Sanikop    attributes = a;
40*57696d54SAkhilesh Sanikop } // alternate constructor
41*57696d54SAkhilesh Sanikop 
42*57696d54SAkhilesh Sanikop // Destructor.
~Attributes(void)43*57696d54SAkhilesh Sanikop Attributes::~Attributes(void) {
44*57696d54SAkhilesh Sanikop    numAttrs--;
45*57696d54SAkhilesh Sanikop } // Attributes destructor
46*57696d54SAkhilesh Sanikop 
Setup(void)47*57696d54SAkhilesh Sanikop void Attributes::Setup(void) {
48*57696d54SAkhilesh Sanikop    ostringstream temp;
49*57696d54SAkhilesh Sanikop 
50*57696d54SAkhilesh Sanikop    // Most bits are undefined, so start by giving them an
51*57696d54SAkhilesh Sanikop    // appropriate name
52*57696d54SAkhilesh Sanikop    for (int i = 0; i < NUM_ATR; i++) {
53*57696d54SAkhilesh Sanikop       temp.str("");
54*57696d54SAkhilesh Sanikop       temp << "Undefined bit #" << i;
55*57696d54SAkhilesh Sanikop       Attributes::atNames[i] = temp.str();
56*57696d54SAkhilesh Sanikop    } // for
57*57696d54SAkhilesh Sanikop 
58*57696d54SAkhilesh Sanikop    // Now reset those names that are defined....
59*57696d54SAkhilesh Sanikop    atNames[0] = "system partition"; // required for computer to operate
60*57696d54SAkhilesh Sanikop    atNames[1] = "hide from EFI";
61*57696d54SAkhilesh Sanikop    atNames[2] = "legacy BIOS bootable";
62*57696d54SAkhilesh Sanikop    atNames[60] = "read-only";
63*57696d54SAkhilesh Sanikop    atNames[62] = "hidden";
64*57696d54SAkhilesh Sanikop    atNames[63] = "do not automount";
65*57696d54SAkhilesh Sanikop }  // Attributes::Setup()
66*57696d54SAkhilesh Sanikop 
67*57696d54SAkhilesh Sanikop // Display current attributes to user
DisplayAttributes(void)68*57696d54SAkhilesh Sanikop void Attributes::DisplayAttributes(void) {
69*57696d54SAkhilesh Sanikop    uint32_t i;
70*57696d54SAkhilesh Sanikop    int numSet = 0;
71*57696d54SAkhilesh Sanikop 
72*57696d54SAkhilesh Sanikop    cout << "Attribute value is ";
73*57696d54SAkhilesh Sanikop    cout.setf(ios::uppercase);
74*57696d54SAkhilesh Sanikop    cout.fill('0');
75*57696d54SAkhilesh Sanikop    cout.width(16);
76*57696d54SAkhilesh Sanikop    cout << hex << attributes << dec << ". Set fields are:\n";
77*57696d54SAkhilesh Sanikop    for (i = 0; i < NUM_ATR; i++) {
78*57696d54SAkhilesh Sanikop       if ((UINT64_C(1) << i) & attributes) {
79*57696d54SAkhilesh Sanikop          cout << i << " (" << GetAttributeName(i) << ")" << "\n";
80*57696d54SAkhilesh Sanikop          numSet++;
81*57696d54SAkhilesh Sanikop       } // if
82*57696d54SAkhilesh Sanikop    } // for
83*57696d54SAkhilesh Sanikop    cout.fill(' ');
84*57696d54SAkhilesh Sanikop    if (numSet == 0)
85*57696d54SAkhilesh Sanikop       cout << "  No fields set\n";
86*57696d54SAkhilesh Sanikop    cout << "\n";
87*57696d54SAkhilesh Sanikop } // Attributes::DisplayAttributes()
88*57696d54SAkhilesh Sanikop 
89*57696d54SAkhilesh Sanikop // Display attributes for a partition. Note that partNum is just passed for
90*57696d54SAkhilesh Sanikop // immediate display; it's not used to access a particular partition.
ShowAttributes(const uint32_t partNum)91*57696d54SAkhilesh Sanikop void Attributes::ShowAttributes(const uint32_t partNum) {
92*57696d54SAkhilesh Sanikop    uint32_t bitNum;
93*57696d54SAkhilesh Sanikop    bool bitset;
94*57696d54SAkhilesh Sanikop 
95*57696d54SAkhilesh Sanikop    for (bitNum = 0; bitNum < 64; bitNum++) {
96*57696d54SAkhilesh Sanikop       bitset = (UINT64_C(1) << bitNum) & attributes;
97*57696d54SAkhilesh Sanikop       if (bitset) {
98*57696d54SAkhilesh Sanikop          cout << partNum+1 << ":" << bitNum << ":" << bitset
99*57696d54SAkhilesh Sanikop          << " (" << GetAttributeName(bitNum) << ")" << endl;
100*57696d54SAkhilesh Sanikop       } // if
101*57696d54SAkhilesh Sanikop    } // for
102*57696d54SAkhilesh Sanikop } // Attributes::ShowAttributes
103*57696d54SAkhilesh Sanikop 
104*57696d54SAkhilesh Sanikop // Prompt user for attribute changes
ChangeAttributes(void)105*57696d54SAkhilesh Sanikop void Attributes::ChangeAttributes(void) {
106*57696d54SAkhilesh Sanikop    int response;
107*57696d54SAkhilesh Sanikop    uint64_t bitValue;
108*57696d54SAkhilesh Sanikop 
109*57696d54SAkhilesh Sanikop    cout << "Known attributes are:\n";
110*57696d54SAkhilesh Sanikop    ListAttributes();
111*57696d54SAkhilesh Sanikop    cout << "\n";
112*57696d54SAkhilesh Sanikop 
113*57696d54SAkhilesh Sanikop    do {
114*57696d54SAkhilesh Sanikop       DisplayAttributes();
115*57696d54SAkhilesh Sanikop       response = GetNumber(0, NUM_ATR, 64,
116*57696d54SAkhilesh Sanikop                            "Toggle which attribute field (0-63, 64 or <Enter> to exit): ");
117*57696d54SAkhilesh Sanikop       if (response != 64) {
118*57696d54SAkhilesh Sanikop          bitValue = UINT64_C(1) << response; // Find the integer value of the bit
119*57696d54SAkhilesh Sanikop          if (bitValue & attributes) { // bit is set
120*57696d54SAkhilesh Sanikop             attributes &= ~bitValue; // so unset it
121*57696d54SAkhilesh Sanikop 	         cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
122*57696d54SAkhilesh Sanikop          } else { // bit is not set
123*57696d54SAkhilesh Sanikop             attributes |= bitValue; // so set it
124*57696d54SAkhilesh Sanikop             cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
125*57696d54SAkhilesh Sanikop          } // if/else
126*57696d54SAkhilesh Sanikop       } // if
127*57696d54SAkhilesh Sanikop    } while (response != 64);
128*57696d54SAkhilesh Sanikop } // Attributes::ChangeAttributes()
129*57696d54SAkhilesh Sanikop 
130*57696d54SAkhilesh Sanikop // Display all defined attributes on the screen (omits undefined bits).
ListAttributes(void)131*57696d54SAkhilesh Sanikop void Attributes::ListAttributes(void) {
132*57696d54SAkhilesh Sanikop    uint32_t bitNum;
133*57696d54SAkhilesh Sanikop    string tempAttr;
134*57696d54SAkhilesh Sanikop 
135*57696d54SAkhilesh Sanikop    for (bitNum = 0; bitNum < NUM_ATR; bitNum++) {
136*57696d54SAkhilesh Sanikop       tempAttr = GetAttributeName(bitNum);
137*57696d54SAkhilesh Sanikop       if (tempAttr.substr(0, 15) != "Undefined bit #" )
138*57696d54SAkhilesh Sanikop          cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n";
139*57696d54SAkhilesh Sanikop    } // for
140*57696d54SAkhilesh Sanikop } // Attributes::ListAttributes
141*57696d54SAkhilesh Sanikop 
142*57696d54SAkhilesh Sanikop // multifaceted attributes access
143*57696d54SAkhilesh Sanikop // returns true upon success, false upon failure
OperateOnAttributes(const uint32_t partNum,const string & attributeOperator,const string & attributeBits)144*57696d54SAkhilesh Sanikop bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) {
145*57696d54SAkhilesh Sanikop 
146*57696d54SAkhilesh Sanikop    // attribute access opcode
147*57696d54SAkhilesh Sanikop    typedef enum {
148*57696d54SAkhilesh Sanikop       ao_or, ao_nand, ao_xor, ao_assignall,  // operate on all attributes (bitmask)
149*57696d54SAkhilesh Sanikop       ao_unknown, // must be after bitmask operators and before bitnum operators
150*57696d54SAkhilesh Sanikop       ao_set, ao_clear, ao_toggle, ao_get    // operate on a single attribute (bitnum)
151*57696d54SAkhilesh Sanikop    } attribute_opcode_t; // typedef enum
152*57696d54SAkhilesh Sanikop 
153*57696d54SAkhilesh Sanikop    // translate attribute operator into an attribute opcode
154*57696d54SAkhilesh Sanikop    attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet
155*57696d54SAkhilesh Sanikop       if      (attributeOperator == "or")      attributeOpcode = ao_or;
156*57696d54SAkhilesh Sanikop       else if (attributeOperator == "nand")    attributeOpcode = ao_nand;
157*57696d54SAkhilesh Sanikop       else if (attributeOperator == "xor")     attributeOpcode = ao_xor;
158*57696d54SAkhilesh Sanikop       else if (attributeOperator == "=")       attributeOpcode = ao_assignall;
159*57696d54SAkhilesh Sanikop       else if (attributeOperator == "set")     attributeOpcode = ao_set;
160*57696d54SAkhilesh Sanikop       else if (attributeOperator == "clear")   attributeOpcode = ao_clear;
161*57696d54SAkhilesh Sanikop       else if (attributeOperator == "toggle")  attributeOpcode = ao_toggle;
162*57696d54SAkhilesh Sanikop       else if (attributeOperator == "get")     attributeOpcode = ao_get;
163*57696d54SAkhilesh Sanikop       else {
164*57696d54SAkhilesh Sanikop          cerr << "Unknown attributes operator: " << attributeOperator << endl;
165*57696d54SAkhilesh Sanikop          return false;
166*57696d54SAkhilesh Sanikop       } // else
167*57696d54SAkhilesh Sanikop    } // attributeOpcode
168*57696d54SAkhilesh Sanikop 
169*57696d54SAkhilesh Sanikop    // get bit mask if operating on entire attribute set
170*57696d54SAkhilesh Sanikop    uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) {
171*57696d54SAkhilesh Sanikop       if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) {
172*57696d54SAkhilesh Sanikop          cerr << "Could not convert hex attribute mask" << endl;
173*57696d54SAkhilesh Sanikop          return false;
174*57696d54SAkhilesh Sanikop       } // if
175*57696d54SAkhilesh Sanikop    }} // attributeBitMask, if
176*57696d54SAkhilesh Sanikop 
177*57696d54SAkhilesh Sanikop    // get bit number and calculate bit mask if operating on a single attribute
178*57696d54SAkhilesh Sanikop    int bitNum; { if (attributeOpcode > ao_unknown) {
179*57696d54SAkhilesh Sanikop       if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) {
180*57696d54SAkhilesh Sanikop          cerr << "Could not convert bit number" << endl;
181*57696d54SAkhilesh Sanikop          return false;
182*57696d54SAkhilesh Sanikop       } // if
183*57696d54SAkhilesh Sanikop       const uint64_t one = 1;
184*57696d54SAkhilesh Sanikop       attributeBitMask = one << bitNum;
185*57696d54SAkhilesh Sanikop    }} // bitNum, if
186*57696d54SAkhilesh Sanikop 
187*57696d54SAkhilesh Sanikop    switch (attributeOpcode) {
188*57696d54SAkhilesh Sanikop       // assign all attributes at once
189*57696d54SAkhilesh Sanikop       case ao_assignall:  attributes = attributeBitMask;    break;
190*57696d54SAkhilesh Sanikop 
191*57696d54SAkhilesh Sanikop       // set individual attribute(s)
192*57696d54SAkhilesh Sanikop       case ao_set:
193*57696d54SAkhilesh Sanikop       case ao_or:         attributes |= attributeBitMask;   break;
194*57696d54SAkhilesh Sanikop 
195*57696d54SAkhilesh Sanikop       // clear individual attribute(s)
196*57696d54SAkhilesh Sanikop       case ao_clear:
197*57696d54SAkhilesh Sanikop       case ao_nand:       attributes &= ~attributeBitMask;  break;
198*57696d54SAkhilesh Sanikop 
199*57696d54SAkhilesh Sanikop       // toggle individual attribute(s)
200*57696d54SAkhilesh Sanikop       case ao_toggle:
201*57696d54SAkhilesh Sanikop       case ao_xor:        attributes ^= attributeBitMask;   break;
202*57696d54SAkhilesh Sanikop 
203*57696d54SAkhilesh Sanikop       // display a single attribute
204*57696d54SAkhilesh Sanikop       case ao_get: {
205*57696d54SAkhilesh Sanikop          cout << partNum+1 << ":" << bitNum << ":"
206*57696d54SAkhilesh Sanikop               << bool (attributeBitMask & attributes) << endl;
207*57696d54SAkhilesh Sanikop          break;
208*57696d54SAkhilesh Sanikop       } // case ao_get
209*57696d54SAkhilesh Sanikop 
210*57696d54SAkhilesh Sanikop       default: break; // will never get here
211*57696d54SAkhilesh Sanikop    } // switch
212*57696d54SAkhilesh Sanikop 
213*57696d54SAkhilesh Sanikop    return true;
214*57696d54SAkhilesh Sanikop } // Attributes::OperateOnAttributes()
215*57696d54SAkhilesh Sanikop 
216*57696d54SAkhilesh Sanikop /*******************************
217*57696d54SAkhilesh Sanikop *                             *
218*57696d54SAkhilesh Sanikop * Non-class support functions *
219*57696d54SAkhilesh Sanikop *                             *
220*57696d54SAkhilesh Sanikop *******************************/
221*57696d54SAkhilesh Sanikop 
222*57696d54SAkhilesh Sanikop // Display attributes
operator <<(ostream & os,const Attributes & data)223*57696d54SAkhilesh Sanikop ostream & operator<<(ostream & os, const Attributes & data) {
224*57696d54SAkhilesh Sanikop    os << data.GetAttributes();
225*57696d54SAkhilesh Sanikop    return os;
226*57696d54SAkhilesh Sanikop } // operator<<()
227