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