2 * Copyright (C) 2011 Sansar Choinyambuu
3 * HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "tcg_pts_attr_unix_file_meta.h"
18 #include <pa_tnc/pa_tnc_msg.h>
19 #include <bio/bio_writer.h>
20 #include <bio/bio_reader.h>
21 #include <utils/linked_list.h>
24 typedef struct private_tcg_pts_attr_file_meta_t private_tcg_pts_attr_file_meta_t
;
27 * Unix-Style File Metadata
28 * see section 3.17.3 of PTS Protocol: Binding to TNC IF-M Specification
31 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
32 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 * | Number of Files included |
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 * | Number of Files included |
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * | File metadata Length | Type | Reserved |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | File Create Time |
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | File Create Time |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * | Last Modify Time |
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * | Last Modify Time |
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * | Last Access Time |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 * | Last Access Time |
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 * ~ Filename (Variable Length) ~
64 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 * ...........................
68 #define PTS_FILE_META_SIZE 8
69 #define PTS_FILE_MEAS_RESERVED 0x00
72 * Private data of an tcg_pts_attr_file_meta_t object.
74 struct private_tcg_pts_attr_file_meta_t
{
77 * Public members of tcg_pts_attr_file_meta_t
79 tcg_pts_attr_file_meta_t
public;
104 pts_file_meta_t
*metadata
;
108 METHOD(pa_tnc_attr_t
, get_vendor_id
, pen_t
,
109 private_tcg_pts_attr_file_meta_t
*this)
111 return this->vendor_id
;
114 METHOD(pa_tnc_attr_t
, get_type
, u_int32_t
,
115 private_tcg_pts_attr_file_meta_t
*this)
120 METHOD(pa_tnc_attr_t
, get_value
, chunk_t
,
121 private_tcg_pts_attr_file_meta_t
*this)
126 METHOD(pa_tnc_attr_t
, get_noskip_flag
, bool,
127 private_tcg_pts_attr_file_meta_t
*this)
129 return this->noskip_flag
;
132 METHOD(pa_tnc_attr_t
, set_noskip_flag
,void,
133 private_tcg_pts_attr_file_meta_t
*this, bool noskip
)
135 this->noskip_flag
= noskip
;
138 METHOD(pa_tnc_attr_t
, build
, void,
139 private_tcg_pts_attr_file_meta_t
*this)
141 bio_writer_t
*writer
;
142 enumerator_t
*enumerator
;
143 pts_file_metadata_t
*entry
;
144 u_int64_t number_of_files
;
146 number_of_files
= this->metadata
->get_file_count(this->metadata
);
147 writer
= bio_writer_create(PTS_FILE_META_SIZE
);
149 /* Write the 64 bit integer field - number of files as two 32 bit parts */
150 writer
->write_uint32(writer
, number_of_files
>> 32);
151 writer
->write_uint32(writer
, number_of_files
& 0xffffffff);
153 enumerator
= this->metadata
->create_enumerator(this->metadata
);
154 while (enumerator
->enumerate(enumerator
, &entry
))
156 writer
->write_uint16(writer
, PTS_FILE_METADATA_SIZE
+ strlen(entry
->filename
));
157 writer
->write_uint8 (writer
, entry
->type
);
158 writer
->write_uint8 (writer
, PTS_FILE_MEAS_RESERVED
);
160 /* Write the 64 bit integer fields as two 32 bit parts */
161 writer
->write_uint32(writer
, entry
->filesize
>> 32);
162 writer
->write_uint32(writer
, entry
->filesize
& 0xffffffff);
163 writer
->write_uint32(writer
, ((u_int64_t
)entry
->created
) >> 32);
164 writer
->write_uint32(writer
, ((u_int64_t
)entry
->created
) & 0xffffffff);
165 writer
->write_uint32(writer
, ((u_int64_t
)entry
->modified
) >> 32);
166 writer
->write_uint32(writer
, ((u_int64_t
)entry
->modified
) & 0xffffffff);
167 writer
->write_uint32(writer
, ((u_int64_t
)entry
->accessed
) >> 32);
168 writer
->write_uint32(writer
, ((u_int64_t
)entry
->accessed
) & 0xffffffff);
169 writer
->write_uint32(writer
, entry
->owner
>> 32);
170 writer
->write_uint32(writer
, entry
->owner
& 0xffffffff);
171 writer
->write_uint32(writer
, entry
->group
>> 32);
172 writer
->write_uint32(writer
, entry
->group
& 0xffffffff);
174 writer
->write_data (writer
, chunk_create(entry
->filename
, strlen(entry
->filename
)));
176 enumerator
->destroy(enumerator
);
178 this->value
= chunk_clone(writer
->get_buf(writer
));
179 writer
->destroy(writer
);
182 METHOD(pa_tnc_attr_t
, process
, status_t
,
183 private_tcg_pts_attr_file_meta_t
*this, u_int32_t
*offset
)
185 bio_reader_t
*reader
;
186 pts_file_metadata_t
*entry
;
189 u_int32_t number_of_files32
;
191 u_int16_t meta_length
;
192 pts_file_type_t type
;
197 u_int32_t filesize32
;
200 u_int32_t create_time32
;
201 time_t create_time_t
;
203 u_int32_t modify_time32
;
204 time_t modify_time_t
;
206 u_int32_t access_time32
;
207 time_t access_time_t
;
210 u_int32_t owner_id32
;
213 u_int32_t group_id32
;
218 status_t status
= FAILED
;
220 if (this->value
.len
< PTS_FILE_META_SIZE
)
222 DBG1(DBG_TNC
, "insufficient data for PTS Unix-Style file metadata header");
226 reader
= bio_reader_create(this->value
);
228 reader
->read_uint32(reader
, &number_of_files32
);
229 number_of_files
= (sizeof(number_of_files
) > 4) ? number_of_files32
<< 32 : 0;
230 reader
->read_uint32(reader
, &number_of_files32
);
231 number_of_files
+= number_of_files32
;
233 this->metadata
= pts_file_meta_create();
235 while (number_of_files
--)
237 if (!reader
->read_uint16(reader
, &meta_length
))
239 DBG1(DBG_TNC
, "insufficient data for PTS file metadata length");
242 if (!reader
->read_uint8 (reader
, &type8
))
244 DBG1(DBG_TNC
, "insufficient data for file type");
247 type
= (pts_file_type_t
)type8
;
248 if (!reader
->read_uint8 (reader
, &reserved
))
250 DBG1(DBG_TNC
, "insufficient data for reserved field");
253 if (!reader
->read_uint32(reader
, &filesize32
))
255 DBG1(DBG_TNC
, "insufficient data for file size");
258 filesize
= (sizeof(filesize
) > 4) ? filesize32
<< 32 : 0;
259 if (!reader
->read_uint32(reader
, &filesize32
))
261 DBG1(DBG_TNC
, "insufficient data for file size");
264 filesize
+= filesize32
;
266 if (!reader
->read_uint32(reader
, &create_time32
))
268 DBG1(DBG_TNC
, "insufficient data for file size");
271 create_time
= (sizeof(create_time
) > 4) ? create_time32
<< 32 : 0;
272 if (!reader
->read_uint32(reader
, &create_time32
))
274 DBG1(DBG_TNC
, "insufficient data for file size");
277 create_time
+= create_time32
;
278 create_time_t
= (time_t)create_time
;
280 if (!reader
->read_uint32(reader
, &modify_time32
))
282 DBG1(DBG_TNC
, "insufficient data for file size");
285 modify_time
= (sizeof(modify_time
) > 4) ? modify_time32
<< 32 : 0;
286 if (!reader
->read_uint32(reader
, &modify_time32
))
288 DBG1(DBG_TNC
, "insufficient data for file size");
291 modify_time
+= modify_time32
;
292 modify_time_t
= (time_t)modify_time
;
294 if (!reader
->read_uint32(reader
, &access_time32
))
296 DBG1(DBG_TNC
, "insufficient data for file size");
299 access_time
= (sizeof(access_time
) > 4) ? access_time32
<< 32 : 0;
300 if (!reader
->read_uint32(reader
, &access_time32
))
302 DBG1(DBG_TNC
, "insufficient data for file size");
305 access_time
+= access_time32
;
306 access_time_t
= (time_t)access_time
;
308 if (!reader
->read_uint32(reader
, &owner_id32
))
310 DBG1(DBG_TNC
, "insufficient data for file size");
313 owner_id
= (sizeof(owner_id
) > 4) ? owner_id32
<< 32 : 0;
314 if (!reader
->read_uint32(reader
, &owner_id32
))
316 DBG1(DBG_TNC
, "insufficient data for file size");
319 owner_id
+= owner_id32
;
321 if (!reader
->read_uint32(reader
, &group_id32
))
323 DBG1(DBG_TNC
, "insufficient data for file size");
326 group_id
= (sizeof(group_id
) > 4) ? group_id32
<< 32 : 0;
327 if (!reader
->read_uint32(reader
, &group_id32
))
329 DBG1(DBG_TNC
, "insufficient data for file size");
332 group_id
+= group_id32
;
334 if (!reader
->read_data(reader
, meta_length
- PTS_FILE_METADATA_SIZE
, &filename
))
336 DBG1(DBG_TNC
, "insufficient data for filename");
340 len
= min(filename
.len
, BUF_LEN
- 1);
341 memcpy(buf
, filename
.ptr
, len
);
344 entry
= malloc_thing(pts_file_metadata_t
);
345 entry
->filename
= strdup(buf
);
346 entry
->meta_length
= PTS_FILE_METADATA_SIZE
+ strlen(entry
->filename
);
348 entry
->filesize
= filesize
;
349 entry
->created
= create_time_t
;
350 entry
->modified
= modify_time_t
;
351 entry
->accessed
= access_time_t
;
352 entry
->owner
= owner_id
;
353 entry
->group
= group_id
;
355 this->metadata
->add(this->metadata
, entry
);
360 reader
->destroy(reader
);
364 METHOD(pa_tnc_attr_t
, destroy
, void,
365 private_tcg_pts_attr_file_meta_t
*this)
367 this->metadata
->destroy(this->metadata
);
368 free(this->value
.ptr
);
372 METHOD(tcg_pts_attr_file_meta_t
, get_metadata
, pts_file_meta_t
*,
373 private_tcg_pts_attr_file_meta_t
*this)
375 return this->metadata
;
379 * Described in header.
381 pa_tnc_attr_t
*tcg_pts_attr_unix_file_meta_create(pts_file_meta_t
*metadata
)
383 private_tcg_pts_attr_file_meta_t
*this;
387 .pa_tnc_attribute
= {
388 .get_vendor_id
= _get_vendor_id
,
389 .get_type
= _get_type
,
390 .get_value
= _get_value
,
391 .get_noskip_flag
= _get_noskip_flag
,
392 .set_noskip_flag
= _set_noskip_flag
,
397 .get_metadata
= _get_metadata
,
399 .vendor_id
= PEN_TCG
,
400 .type
= TCG_PTS_UNIX_FILE_META
,
401 .metadata
= metadata
,
404 return &this->public.pa_tnc_attribute
;
409 * Described in header.
411 pa_tnc_attr_t
*tcg_pts_attr_unix_file_meta_create_from_data(chunk_t data
)
413 private_tcg_pts_attr_file_meta_t
*this;
417 .pa_tnc_attribute
= {
418 .get_vendor_id
= _get_vendor_id
,
419 .get_type
= _get_type
,
420 .get_value
= _get_value
,
421 .get_noskip_flag
= _get_noskip_flag
,
422 .set_noskip_flag
= _set_noskip_flag
,
427 .get_metadata
= _get_metadata
,
429 .vendor_id
= PEN_TCG
,
430 .type
= TCG_PTS_UNIX_FILE_META
,
431 .value
= chunk_clone(data
),
434 return &this->public.pa_tnc_attribute
;