1 |
|
|
/** |
2 |
|
|
* This file is part of the CernVM File System |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#include "sync_item_tar.h" |
6 |
|
|
|
7 |
|
|
#include <string> |
8 |
|
|
|
9 |
|
|
#include "directory_entry.h" |
10 |
|
|
#include "duplex_libarchive.h" |
11 |
|
|
#include "ingestion/ingestion_source.h" |
12 |
|
|
#include "platform.h" |
13 |
|
|
#include "sync_union_tarball.h" |
14 |
|
|
#include "util_concurrency.h" |
15 |
|
|
|
16 |
|
|
namespace publish { |
17 |
|
|
|
18 |
|
|
SyncItemTar::SyncItemTar(const std::string &relative_parent_path, |
19 |
|
|
const std::string &filename, struct archive *archive, |
20 |
|
|
struct archive_entry *entry, |
21 |
|
|
Signal *read_archive_signal, |
22 |
|
|
const SyncUnion *union_engine) |
23 |
|
|
: SyncItem(relative_parent_path, filename, union_engine, kItemUnknown), |
24 |
|
|
archive_(archive), |
25 |
|
|
archive_entry_(entry), |
26 |
|
|
obtained_tar_stat_(false), |
27 |
|
|
read_archive_signal_(read_archive_signal) { |
28 |
|
|
GetStatFromTar(); |
29 |
|
|
} |
30 |
|
|
|
31 |
|
|
void SyncItemTar::StatScratch(const bool refresh) const { |
32 |
|
|
if (scratch_stat_.obtained && !refresh) return; |
33 |
|
|
scratch_stat_.stat = GetStatFromTar(); |
34 |
|
|
scratch_stat_.error_code = 0; |
35 |
|
|
scratch_stat_.obtained = true; |
36 |
|
|
} |
37 |
|
|
|
38 |
|
|
SyncItemType SyncItemTar::GetScratchFiletype() const { |
39 |
|
|
assert(archive_entry_); |
40 |
|
|
switch (archive_entry_filetype(archive_entry_)) { |
41 |
|
|
case AE_IFREG: { |
42 |
|
|
return kItemFile; |
43 |
|
|
break; |
44 |
|
|
} |
45 |
|
|
case AE_IFLNK: { |
46 |
|
|
return kItemSymlink; |
47 |
|
|
break; |
48 |
|
|
} |
49 |
|
|
case AE_IFSOCK: { |
50 |
|
|
return kItemSocket; |
51 |
|
|
break; |
52 |
|
|
} |
53 |
|
|
case AE_IFCHR: { |
54 |
|
|
return kItemCharacterDevice; |
55 |
|
|
break; |
56 |
|
|
} |
57 |
|
|
case AE_IFBLK: { |
58 |
|
|
return kItemBlockDevice; |
59 |
|
|
break; |
60 |
|
|
} |
61 |
|
|
case AE_IFDIR: { |
62 |
|
|
return kItemDir; |
63 |
|
|
break; |
64 |
|
|
} |
65 |
|
|
case AE_IFIFO: { |
66 |
|
|
return kItemFifo; |
67 |
|
|
break; |
68 |
|
|
} |
69 |
|
|
default: |
70 |
|
|
return kItemUnknown; |
71 |
|
|
break; |
72 |
|
|
} |
73 |
|
|
} |
74 |
|
|
|
75 |
|
|
bool SyncItemTar::IsType(const SyncItemType expected_type) const { |
76 |
|
|
if (scratch_type_ == kItemUnknown) { |
77 |
|
|
scratch_type_ = GetScratchFiletype(); |
78 |
|
|
} |
79 |
|
|
return scratch_type_ == expected_type; |
80 |
|
|
} |
81 |
|
|
|
82 |
|
|
platform_stat64 SyncItemTar::GetStatFromTar() const { |
83 |
|
|
assert(archive_entry_); |
84 |
|
|
if (obtained_tar_stat_) return tar_stat_; |
85 |
|
|
|
86 |
|
|
const struct stat *entry_stat = archive_entry_stat(archive_entry_); |
87 |
|
|
assert(NULL != entry_stat); |
88 |
|
|
|
89 |
|
|
tar_stat_.st_mode = entry_stat->st_mode; |
90 |
|
|
tar_stat_.st_uid = entry_stat->st_uid; |
91 |
|
|
tar_stat_.st_gid = entry_stat->st_gid; |
92 |
|
|
tar_stat_.st_size = entry_stat->st_size; |
93 |
|
|
tar_stat_.st_mtime = entry_stat->st_mtime; |
94 |
|
|
tar_stat_.st_nlink = entry_stat->st_nlink; |
95 |
|
|
|
96 |
|
|
if (IsDirectory()) { |
97 |
|
|
tar_stat_.st_size = 4096; |
98 |
|
|
} |
99 |
|
|
|
100 |
|
|
obtained_tar_stat_ = true; |
101 |
|
|
|
102 |
|
|
return tar_stat_; |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
catalog::DirectoryEntryBase SyncItemTar::CreateBasicCatalogDirent() const { |
106 |
|
|
assert(obtained_tar_stat_); |
107 |
|
|
|
108 |
|
|
catalog::DirectoryEntryBase dirent; |
109 |
|
|
|
110 |
|
|
// inode and parent inode is determined at runtime of client |
111 |
|
|
dirent.inode_ = catalog::DirectoryEntry::kInvalidInode; |
112 |
|
|
|
113 |
|
|
// tarfiles do not keep information about the linkcount, so it should always |
114 |
|
|
// appear as zero |
115 |
|
|
assert(this->tar_stat_.st_nlink == 0); |
116 |
|
|
dirent.linkcount_ = 1; |
117 |
|
|
|
118 |
|
|
dirent.mode_ = this->tar_stat_.st_mode; |
119 |
|
|
dirent.uid_ = this->tar_stat_.st_uid; |
120 |
|
|
dirent.gid_ = this->tar_stat_.st_gid; |
121 |
|
|
dirent.size_ = this->tar_stat_.st_size; |
122 |
|
|
dirent.mtime_ = this->tar_stat_.st_mtime; |
123 |
|
|
dirent.checksum_ = this->GetContentHash(); |
124 |
|
|
dirent.is_external_file_ = this->IsExternalData(); |
125 |
|
|
dirent.compression_algorithm_ = this->GetCompressionAlgorithm(); |
126 |
|
|
|
127 |
|
|
dirent.name_.Assign(this->filename().data(), this->filename().length()); |
128 |
|
|
|
129 |
|
|
if (this->IsSymlink()) { |
130 |
|
|
std::string symlink(archive_entry_symlink(archive_entry_)); |
131 |
|
|
dirent.symlink_.Assign(symlink.c_str(), symlink.length()); |
132 |
|
|
} |
133 |
|
|
|
134 |
|
|
if (this->IsCharacterDevice() || this->IsBlockDevice()) { |
135 |
|
|
dirent.size_ = makedev(GetRdevMajor(), GetRdevMinor()); |
136 |
|
|
} |
137 |
|
|
|
138 |
|
|
assert(dirent.IsRegular() || dirent.IsDirectory() || dirent.IsLink() || |
139 |
|
|
dirent.IsSpecial()); |
140 |
|
|
|
141 |
|
|
return dirent; |
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
IngestionSource *SyncItemTar::CreateIngestionSource() const { |
145 |
|
|
return new TarIngestionSource(GetUnionPath(), archive_, archive_entry_, |
146 |
|
|
read_archive_signal_); |
147 |
|
|
} |
148 |
|
|
} // namespace publish |