You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
7.4 KiB
228 lines
7.4 KiB
// attributes.cc |
|
// Class to manage partition attribute codes. These are binary bit fields, |
|
// of which only four are currently (2/2011) documented on Wikipedia, and |
|
// two others found from other sources. |
|
|
|
/* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed |
|
under the terms of the GNU GPL version 2, as detailed in the COPYING file. */ |
|
|
|
#define __STDC_LIMIT_MACROS |
|
#ifndef __STDC_CONSTANT_MACROS |
|
#define __STDC_CONSTANT_MACROS |
|
#endif |
|
|
|
#include <stdint.h> |
|
#include <stdio.h> |
|
#include <iostream> |
|
#include <sstream> |
|
|
|
#include "attributes.h" |
|
#include "support.h" |
|
|
|
using namespace std; |
|
|
|
string Attributes::atNames[NUM_ATR]; |
|
int Attributes::numAttrs = 0; |
|
//Attributes::staticInit Attributes::staticInitializer; |
|
|
|
// Default constructor |
|
Attributes::Attributes(void) { |
|
numAttrs++; |
|
if (numAttrs == 1) |
|
Setup(); |
|
attributes = 0; |
|
} // constructor |
|
|
|
// Alternate constructor |
|
Attributes::Attributes(const uint64_t a) { |
|
numAttrs++; |
|
if (numAttrs == 1) |
|
Setup(); |
|
attributes = a; |
|
} // alternate constructor |
|
|
|
// Destructor. |
|
Attributes::~Attributes(void) { |
|
numAttrs--; |
|
} // Attributes destructor |
|
|
|
void Attributes::Setup(void) { |
|
ostringstream temp; |
|
|
|
// Most bits are undefined, so start by giving them an |
|
// appropriate name |
|
for (int i = 0; i < NUM_ATR; i++) { |
|
temp.str(""); |
|
temp << "Undefined bit #" << i; |
|
Attributes::atNames[i] = temp.str(); |
|
} // for |
|
|
|
// Now reset those names that are defined.... |
|
atNames[0] = "system partition"; // required for computer to operate |
|
atNames[1] = "hide from EFI"; |
|
atNames[2] = "legacy BIOS bootable"; |
|
atNames[60] = "read-only"; |
|
atNames[62] = "hidden"; |
|
atNames[63] = "do not automount"; |
|
} // Attributes::Setup() |
|
|
|
// Display current attributes to user |
|
void Attributes::DisplayAttributes(void) { |
|
uint32_t i; |
|
int numSet = 0; |
|
|
|
cout << "Attribute value is "; |
|
cout.setf(ios::uppercase); |
|
cout.fill('0'); |
|
cout.width(16); |
|
cout << hex << attributes << dec << ". Set fields are:\n"; |
|
for (i = 0; i < NUM_ATR; i++) { |
|
if ((UINT64_C(1) << i) & attributes) { |
|
cout << i << " (" << GetAttributeName(i) << ")" << "\n"; |
|
numSet++; |
|
} // if |
|
} // for |
|
cout.fill(' '); |
|
if (numSet == 0) |
|
cout << " No fields set\n"; |
|
cout << "\n"; |
|
} // Attributes::DisplayAttributes() |
|
|
|
// Display attributes for a partition. Note that partNum is just passed for |
|
// immediate display; it's not used to access a particular partition. |
|
void Attributes::ShowAttributes(const uint32_t partNum) { |
|
uint32_t bitNum; |
|
bool bitset; |
|
|
|
for (bitNum = 0; bitNum < 64; bitNum++) { |
|
bitset = (UINT64_C(1) << bitNum) & attributes; |
|
if (bitset) { |
|
cout << partNum+1 << ":" << bitNum << ":" << bitset |
|
<< " (" << GetAttributeName(bitNum) << ")" << endl; |
|
} // if |
|
} // for |
|
} // Attributes::ShowAttributes |
|
|
|
// Prompt user for attribute changes |
|
void Attributes::ChangeAttributes(void) { |
|
int response; |
|
uint64_t bitValue; |
|
|
|
cout << "Known attributes are:\n"; |
|
ListAttributes(); |
|
cout << "\n"; |
|
|
|
do { |
|
DisplayAttributes(); |
|
response = GetNumber(0, NUM_ATR, 64, |
|
"Toggle which attribute field (0-63, 64 or <Enter> to exit): "); |
|
if (response != 64) { |
|
bitValue = UINT64_C(1) << response; // Find the integer value of the bit |
|
if (bitValue & attributes) { // bit is set |
|
attributes &= ~bitValue; // so unset it |
|
cout << "Have disabled the '" << atNames[response] << "' attribute.\n"; |
|
} else { // bit is not set |
|
attributes |= bitValue; // so set it |
|
cout << "Have enabled the '" << atNames[response] << "' attribute.\n"; |
|
} // if/else |
|
} // if |
|
} while (response != 64); |
|
} // Attributes::ChangeAttributes() |
|
|
|
// Display all defined attributes on the screen (omits undefined bits). |
|
void Attributes::ListAttributes(void) { |
|
uint32_t bitNum; |
|
string tempAttr; |
|
|
|
for (bitNum = 0; bitNum < NUM_ATR; bitNum++) { |
|
tempAttr = GetAttributeName(bitNum); |
|
if (tempAttr.substr(0, 15) != "Undefined bit #" ) |
|
cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n"; |
|
} // for |
|
} // Attributes::ListAttributes |
|
|
|
// multifaceted attributes access |
|
// returns true upon success, false upon failure |
|
bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) { |
|
|
|
// attribute access opcode |
|
typedef enum { |
|
ao_or, ao_nand, ao_xor, ao_assignall, // operate on all attributes (bitmask) |
|
ao_unknown, // must be after bitmask operators and before bitnum operators |
|
ao_set, ao_clear, ao_toggle, ao_get // operate on a single attribute (bitnum) |
|
} attribute_opcode_t; // typedef enum |
|
|
|
// translate attribute operator into an attribute opcode |
|
attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet |
|
if (attributeOperator == "or") attributeOpcode = ao_or; |
|
else if (attributeOperator == "nand") attributeOpcode = ao_nand; |
|
else if (attributeOperator == "xor") attributeOpcode = ao_xor; |
|
else if (attributeOperator == "=") attributeOpcode = ao_assignall; |
|
else if (attributeOperator == "set") attributeOpcode = ao_set; |
|
else if (attributeOperator == "clear") attributeOpcode = ao_clear; |
|
else if (attributeOperator == "toggle") attributeOpcode = ao_toggle; |
|
else if (attributeOperator == "get") attributeOpcode = ao_get; |
|
else { |
|
cerr << "Unknown attributes operator: " << attributeOperator << endl; |
|
return false; |
|
} // else |
|
} // attributeOpcode |
|
|
|
// get bit mask if operating on entire attribute set |
|
uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) { |
|
if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) { |
|
cerr << "Could not convert hex attribute mask" << endl; |
|
return false; |
|
} // if |
|
}} // attributeBitMask, if |
|
|
|
// get bit number and calculate bit mask if operating on a single attribute |
|
int bitNum; { if (attributeOpcode > ao_unknown) { |
|
if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) { |
|
cerr << "Could not convert bit number" << endl; |
|
return false; |
|
} // if |
|
const uint64_t one = 1; |
|
attributeBitMask = one << bitNum; |
|
}} // bitNum, if |
|
|
|
switch (attributeOpcode) { |
|
// assign all attributes at once |
|
case ao_assignall: attributes = attributeBitMask; break; |
|
|
|
// set individual attribute(s) |
|
case ao_set: |
|
case ao_or: attributes |= attributeBitMask; break; |
|
|
|
// clear individual attribute(s) |
|
case ao_clear: |
|
case ao_nand: attributes &= ~attributeBitMask; break; |
|
|
|
// toggle individual attribute(s) |
|
case ao_toggle: |
|
case ao_xor: attributes ^= attributeBitMask; break; |
|
|
|
// display a single attribute |
|
case ao_get: { |
|
cout << partNum+1 << ":" << bitNum << ":" |
|
<< bool (attributeBitMask & attributes) << endl; |
|
break; |
|
} // case ao_get |
|
|
|
default: break; // will never get here |
|
} // switch |
|
|
|
return true; |
|
} // Attributes::OperateOnAttributes() |
|
|
|
/******************************* |
|
* * |
|
* Non-class support functions * |
|
* * |
|
*******************************/ |
|
|
|
// Display attributes |
|
ostream & operator<<(ostream & os, const Attributes & data) { |
|
os << data.GetAttributes(); |
|
return os; |
|
} // operator<<()
|
|
|