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 20using namespace std; 21 22string Attributes::atNames[NUM_ATR]; 23int Attributes::numAttrs = 0; 24//Attributes::staticInit Attributes::staticInitializer; 25 26// Default constructor 27Attributes::Attributes(void) { 28 numAttrs++; 29 if (numAttrs == 1) 30 Setup(); 31 attributes = 0; 32} // constructor 33 34// Alternate constructor 35Attributes::Attributes(const uint64_t a) { 36 numAttrs++; 37 if (numAttrs == 1) 38 Setup(); 39 attributes = a; 40} // alternate constructor 41 42// Destructor. 43Attributes::~Attributes(void) { 44 numAttrs--; 45} // Attributes destructor 46 47void 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 68void 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. 91void 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 105void 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). 131void 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 144bool 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 223ostream & operator<<(ostream & os, const Attributes & data) { 224 os << data.GetAttributes(); 225 return os; 226} // operator<<() 227