125 lines
2.5 KiB
C++
125 lines
2.5 KiB
C++
/*
|
|
* \brief TAR record lookup function
|
|
* \author Norman Feske
|
|
* \author Christian Prochaska
|
|
* \date 2012-08-20
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2012-2013 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
#ifndef _LOOKUP_H_
|
|
#define _LOOKUP_H_
|
|
|
|
/* Genode includes */
|
|
#include <os/path.h>
|
|
|
|
/* local includes */
|
|
#include <node.h>
|
|
|
|
namespace File_system {
|
|
|
|
extern char *_tar_base;
|
|
extern size_t _tar_size;
|
|
|
|
typedef Genode::Path<File_system::MAX_PATH_LEN> Absolute_path;
|
|
|
|
struct Lookup_criterion { virtual bool match(char const *path) = 0; };
|
|
|
|
struct Lookup_exact : public Lookup_criterion
|
|
{
|
|
Absolute_path _match_path;
|
|
|
|
Lookup_exact(char const *match_path)
|
|
: _match_path(match_path)
|
|
{
|
|
_match_path.remove_trailing('/');
|
|
}
|
|
|
|
bool match(char const *path)
|
|
{
|
|
Absolute_path test_path(path);
|
|
test_path.remove_trailing('/');
|
|
return _match_path.equals(test_path);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Lookup the Nth record in the specified path
|
|
*/
|
|
struct Lookup_member_of_path : public Lookup_criterion
|
|
{
|
|
Absolute_path _dir_path;
|
|
int const index;
|
|
int cnt;
|
|
|
|
Lookup_member_of_path(char const *dir_path, int index)
|
|
: _dir_path(dir_path), index(index), cnt(0)
|
|
{
|
|
_dir_path.remove_trailing('/');
|
|
}
|
|
|
|
bool match(char const *path)
|
|
{
|
|
Absolute_path test_path(path);
|
|
|
|
if (!test_path.strip_prefix(_dir_path.base()))
|
|
return false;
|
|
|
|
if (!test_path.has_single_element())
|
|
return false;
|
|
|
|
cnt++;
|
|
|
|
/* match only if index is reached */
|
|
if (cnt - 1 != index)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
};
|
|
|
|
Record *_lookup(Lookup_criterion *criterion)
|
|
{
|
|
/* measure size of archive in blocks */
|
|
unsigned block_id = 0, block_cnt = _tar_size/Record::BLOCK_LEN;
|
|
|
|
/* scan metablocks of archive */
|
|
while (block_id < block_cnt) {
|
|
|
|
Record *record = (Record *)(_tar_base + block_id*Record::BLOCK_LEN);
|
|
|
|
/* get infos about current file */
|
|
if (criterion->match(record->name()))
|
|
return record;
|
|
|
|
size_t file_size = record->size();
|
|
|
|
/* some datablocks */ /* one metablock */
|
|
block_id = block_id + (file_size / Record::BLOCK_LEN) + 1;
|
|
|
|
/* round up */
|
|
if (file_size % Record::BLOCK_LEN != 0) block_id++;
|
|
|
|
/* check for end of tar archive */
|
|
if (block_id*Record::BLOCK_LEN >= _tar_size)
|
|
break;
|
|
|
|
/* lookout for empty eof-blocks */
|
|
if (*(_tar_base + (block_id*Record::BLOCK_LEN)) == 0x00)
|
|
if (*(_tar_base + (block_id*Record::BLOCK_LEN + 1)) == 0x00)
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* _LOOKUP_H_ */
|