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