// apexctl.cc // see http://svn.chezphil.org/utils // (C) 2007 Philip Endecott // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include #include #include "Exception.hh" #include "FileDescriptor.hh" #include "utils.hh" #include using namespace std; using namespace boost; using namespace pbe; uint16_t magic = 0x4165; static string read_null_terminated_string(FileDescriptor& fd) { string s; while (1) { char c = fd.binread(); if (c==0) { return s; } s += c; } } static void check_magic(FileDescriptor& fd) { uint16_t m = ntohs(fd.binread()); if (m != magic) { throw "Wrong magic number"; } } static void check_dev(string device) { if (device=="") { throw "You must specify a device using -d"; } } typedef map > env_t; static void load_env(FileDescriptor& fd, int offset, env_t& env, int& size) { fd.seek(offset); check_magic(fd); while (1) { uint8_t flag = fd.binread(); if (flag==0xff) { break; } bool active = flag&0x80; uint8_t id = flag&0x7f; string key; if (env.find(id)==env.end()) { key = read_null_terminated_string(fd); } else { key = env[id].first; } string value = read_null_terminated_string(fd); env[id] = make_pair(key,value); } size = fd.getpos() - offset; } static void save_env(FileDescriptor& fd, int offset, const env_t& env, int size) { fd.seek(offset); check_magic(fd); for (env_t::const_iterator i = env.begin(); i != env.end(); ++i) { int id = i->first; string key = i->second.first; string value = i->second.second; fd.binwrite(id|0x80); fd.writeall(key.c_str(),key.length()+1); fd.writeall(value.c_str(),value.length()+1); } int padlength = max(1L,offset+size-fd.getpos()); string ffs(padlength,0xff); fd.writeall(ffs); } static void printenv(string device, int offset) { FileDescriptor fd(device,FileDescriptor::read_only); env_t env; int size; load_env(fd,offset,env,size); for (env_t::const_iterator i = env.begin(); i != env.end(); ++i) { cout << i->second.first << " = " << i->second.second << "\n"; } } static void getenv(string device, int offset, string variable) { FileDescriptor fd(device,FileDescriptor::read_only); env_t env; int size; load_env(fd,offset,env,size); for (env_t::const_iterator i = env.begin(); i!=env.end(); ++i) { if (i->second.first == variable) { cout << i->second.second << "\n"; return; } } cerr << "Variable not found\n"; exit(2); } static void setenv(string device, int offset, string variable, string value) { FileDescriptor fd(device,FileDescriptor::read_write); env_t env; int size; load_env(fd,offset,env,size); uint8_t id = 0; for (env_t::const_iterator i = env.begin(); i!=env.end(); ++i) { id = i->first + 1; if (i->second.first == variable) { id = i->first; break; } } env[id] = make_pair(variable,value); save_env(fd,offset,env,size); } static void init(string device, int offset, int size) { FileDescriptor fd(device,FileDescriptor::create); fd.seek(offset); fd.binwrite(htons(magic)); string ffs(size-2,0xff); fd.writeall(ffs); } static void usage() { cerr << "Usage:\n" << " apexctl [options] printenv\n" << " apexctl [options] getenv variable\n" << " (exit status 2 if not found)\n" << " apexctl [options] setenv variable value\n" << " apexctl [options] init size\n" << "Options:\n" << " -d device specify /dev/mtd* device containing environment\n" << " -o offset specify offset into device of start of environment\n" << " (in decimal; prefix with 0x for hex)\n"; } int main(int argc, char* argv[]) { try { try { if (argc==1) { usage(); exit(1); } string device=""; int offset=0; for (int i=1; i