|
1 /***************************************************************************** |
|
2 * |
|
3 * $Id$ |
|
4 * |
|
5 ****************************************************************************/ |
|
6 |
|
7 #include <libgen.h> // basename() |
|
8 |
|
9 #include <iostream> |
|
10 #include <iomanip> |
|
11 #include <fstream> |
|
12 using namespace std; |
|
13 |
|
14 #include "CommandFoeWrite.h" |
|
15 |
|
16 /*****************************************************************************/ |
|
17 |
|
18 CommandFoeWrite::CommandFoeWrite(): |
|
19 FoeCommand("foe_write", "Store a file on a slave via FoE.") |
|
20 { |
|
21 } |
|
22 |
|
23 /*****************************************************************************/ |
|
24 |
|
25 string CommandFoeWrite::helpString() const |
|
26 { |
|
27 stringstream str; |
|
28 |
|
29 str << getName() << " [OPTIONS] <FILENAME>" << endl |
|
30 << endl |
|
31 << getBriefDescription() << endl |
|
32 << endl |
|
33 << "This command requires a single slave to be selected." << endl |
|
34 << endl |
|
35 << "Arguments:" << endl |
|
36 << " FILENAME can either be a path to a file, or '-'. In" << endl |
|
37 << " the latter case, data are read from stdin and" << endl |
|
38 << " the --output-file option has to be specified." << endl |
|
39 << endl |
|
40 << "Command-specific options:" << endl |
|
41 << " --output-file -o <file> Target filename on the slave." << endl |
|
42 << " If the FILENAME argument is" << endl |
|
43 << " '-', this is mandatory." << endl |
|
44 << " Otherwise, the basename() of" << endl |
|
45 << " FILENAME is used by default." << endl |
|
46 << " --alias -a <alias>" << endl |
|
47 << " --position -p <pos> Slave selection. See the help" << endl |
|
48 << " of the 'slaves' command." << endl |
|
49 << endl |
|
50 << numericInfo(); |
|
51 |
|
52 return str.str(); |
|
53 } |
|
54 |
|
55 /****************************************************************************/ |
|
56 |
|
57 void CommandFoeWrite::execute(MasterDevice &m, const StringVector &args) |
|
58 { |
|
59 stringstream err; |
|
60 ec_ioctl_slave_foe_t data; |
|
61 ifstream file; |
|
62 SlaveList slaves; |
|
63 string storeFileName; |
|
64 |
|
65 if (args.size() != 1) { |
|
66 err << "'" << getName() << "' takes exactly one argument!"; |
|
67 throwInvalidUsageException(err); |
|
68 } |
|
69 |
|
70 if (args[0] == "-") { |
|
71 loadFoeData(&data, cin); |
|
72 if (getOutputFile().empty()) { |
|
73 err << "Please specify a filename for the slave side" |
|
74 << " with --output-file!"; |
|
75 throwCommandException(err); |
|
76 } else { |
|
77 storeFileName = getOutputFile(); |
|
78 } |
|
79 } else { |
|
80 file.open(args[0].c_str(), ifstream::in | ifstream::binary); |
|
81 if (file.fail()) { |
|
82 err << "Failed to open '" << args[0] << "'!"; |
|
83 throwCommandException(err); |
|
84 } |
|
85 loadFoeData(&data, file); |
|
86 file.close(); |
|
87 if (getOutputFile().empty()) { |
|
88 char *cpy = strdup(args[0].c_str()); // basename can modify |
|
89 // the string contents |
|
90 storeFileName = basename(cpy); |
|
91 free(cpy); |
|
92 } else { |
|
93 storeFileName = getOutputFile(); |
|
94 } |
|
95 } |
|
96 |
|
97 try { |
|
98 m.open(MasterDevice::ReadWrite); |
|
99 } catch (MasterDeviceException &e) { |
|
100 if (data.buffer_size) |
|
101 delete [] data.buffer; |
|
102 throw e; |
|
103 } |
|
104 |
|
105 slaves = selectedSlaves(m); |
|
106 if (slaves.size() != 1) { |
|
107 if (data.buffer_size) |
|
108 delete [] data.buffer; |
|
109 throwSingleSlaveRequired(slaves.size()); |
|
110 } |
|
111 data.slave_position = slaves.front().position; |
|
112 |
|
113 // write data via foe to the slave |
|
114 data.offset = 0; |
|
115 strncpy(data.file_name, storeFileName.c_str(), sizeof(data.file_name)); |
|
116 |
|
117 try { |
|
118 m.writeFoe(&data); |
|
119 } catch (MasterDeviceException &e) { |
|
120 if (data.buffer_size) |
|
121 delete [] data.buffer; |
|
122 if (data.abort_code) { |
|
123 err << "Failed to write via FoE: " |
|
124 << errorString(data.abort_code); |
|
125 throwCommandException(err); |
|
126 } else { |
|
127 throw e; |
|
128 } |
|
129 } |
|
130 |
|
131 if (getVerbosity() == Verbose) { |
|
132 cerr << "FoE writing finished." << endl; |
|
133 } |
|
134 |
|
135 if (data.buffer_size) |
|
136 delete [] data.buffer; |
|
137 } |
|
138 |
|
139 /*****************************************************************************/ |
|
140 |
|
141 void CommandFoeWrite::loadFoeData( |
|
142 ec_ioctl_slave_foe_t *data, |
|
143 const istream &in |
|
144 ) |
|
145 { |
|
146 stringstream err; |
|
147 ostringstream tmp; |
|
148 |
|
149 tmp << in.rdbuf(); |
|
150 string const &contents = tmp.str(); |
|
151 |
|
152 if (getVerbosity() == Verbose) { |
|
153 cerr << "Read " << contents.size() << " bytes of FoE data." << endl; |
|
154 } |
|
155 |
|
156 data->buffer_size = contents.size(); |
|
157 |
|
158 if (data->buffer_size) { |
|
159 // allocate buffer and read file into buffer |
|
160 data->buffer = new uint8_t[data->buffer_size]; |
|
161 contents.copy((char *) data->buffer, contents.size()); |
|
162 } |
|
163 } |
|
164 |
|
165 /*****************************************************************************/ |