49 #ifdef _FORTIFY_SOURCE
50 # undef _FORTIFY_SOURCE
52 #define _FORTIFY_SOURCE 0
56 #if !defined(NCBI_OS_UNIX) && !defined(NCBI_OS_MSWIN)
57 # error "Class CTar can be defined on UNIX and MS-Windows platforms only!"
60 #if defined(NCBI_OS_UNIX)
61 # include "../../../corelib/ncbi_os_unix_p.hpp"
66 # include <sys/mkdev.h>
68 # ifdef HAVE_SYS_SYSMACROS_H
69 # include <sys/sysmacros.h>
71 # ifdef NCBI_OS_DARWIN
75 # define makedev makedev
77 # if !defined(major) || !defined(minor) || !defined(makedev)
78 # error "Device macros undefined in this UNIX build!"
80 #elif defined(NCBI_OS_MSWIN)
81 # include "../../../corelib/ncbi_os_mswin_p.hpp"
83 typedef unsigned int mode_t;
84 typedef unsigned int uid_t;
85 typedef unsigned int gid_t;
89 #define NCBI_USE_ERRCODE_X Util_Compress
90 #define NCBI_MODULE NCBITAR
107 ptr[--
len] = char(
'0' +
char(
val & 7));
119 size_t i = *ptr ? 0 : 1;
120 while (
i <
len && ptr[
i]) {
121 if (!
isspace((
unsigned char) ptr[
i]))
127 while (
i <
len &&
'0' <= ptr[
i] && ptr[
i] <=
'7') {
130 val |= ptr[
i++] -
'0';
132 while (
i <
len && ptr[
i]) {
133 if (!
isspace((
unsigned char) ptr[
i]))
145 ptr[--
len] = (
unsigned char)(
val & 0xFF);
178 val = *ptr++ &
'\x3F';
184 val |= (
unsigned char)(*ptr++);
253 #elif defined(S_IREAD)
258 #elif defined(S_IWRITE)
263 #elif defined(S_IEXEC)
304 #elif defined(S_IREAD)
309 #elif defined(S_IWRITE)
314 #elif defined(S_IEXEC)
319 #elif defined(S_IREAD)
331 #elif defined(S_IREAD)
342 #if defined(S_IFMT) || defined(_S_IFMT)
349 if (!(
mask & 07777)) {
357 static size_t s_Length(
const char* ptr,
size_t maxsize)
359 const char* pos = (
const char*) memchr(ptr,
'\0', maxsize);
360 return pos ? (size_t)(pos - ptr) : maxsize;
371 #define ALIGN_SIZE(size) (((size) + (BLOCK_SIZE-1)) & ~(BLOCK_SIZE-1))
372 #define OFFSET_OF(size) ( (size) & (BLOCK_SIZE-1))
373 #define BLOCK_OF(pos) ((pos) >> 9)
374 #define SIZE_OF(blk) ((blk) << 9)
377 #define BLOCK_SIZE SIZE_OF(1)
438 size_t len =
sizeof(h->
checksum) - (isgnu ? 2 : 1);
442 unsigned long checksum = 0;
443 const unsigned char* p = (
const unsigned char*) block->
buffer;
486 if (
sizeof(
int) >= 4 &&
sizeof(
m_Stat.
orig.st_rdev) >= 4) {
487 return (*((
unsigned int*) &
m_Stat.
orig.st_rdev) >> 16) & 0xFFFF;
490 return (
unsigned int)(-1);
501 if (
sizeof(
int) >= 4 &&
sizeof(
m_Stat.
orig.st_rdev) >= 4) {
502 return *((
unsigned int*) &
m_Stat.
orig.st_rdev) & 0xFFFF;
505 return (
unsigned int)(-1);
512 memset(
buf,
'-',
sizeof(
buf));
585 string user(
info.GetUserName());
589 string group(
info.GetGroupName());
593 return user +
'/' + group;
607 unsigned int major =
info.GetMajor();
608 unsigned int minor =
info.GetMinor();
616 info.GetSize() == 0) {
634 os <<
" -> " <<
info.GetLinkName();
655 if (!strerr || !*strerr
659 ::sprintf(errbuf,
"Error %d", x_errno);
660 }
else if (x_errno != -1) {
661 ::sprintf(errbuf,
"Error 0x%08X", (
unsigned int) x_errno);
663 ::strcpy (errbuf,
"Unknown error (-1)");
668 return string(
": ") + strerr;
673 const string& entryname)
690 if (!entryname.empty()) {
691 result +=
", while in '" + entryname +
'\'';
708 for (
size_t i = 0;
i <
len; ++
i) {
719 if (!
text && maxsize > 1 && !*field) {
730 return check && !retval.empty() ?
"\\0" + retval : retval;
734 #if !defined(__GNUC__) && !defined(offsetof)
735 # define offsetof(T, F) ((char*) &(((T*) 0)->F) - (char*) 0)
738 #define TAR_PRINTABLE_EX(field, text, size) \
739 "@" + s_OffsetAsString((size_t) offsetof(STarHeader, field)) + \
740 "[" NCBI_AS_STRING(field) "]:" + \
741 string(14 - sizeof(NCBI_AS_STRING(field)), ' ') + \
742 '"' + s_Printable(h->field, size, text || excpt) + '"'
744 #define TAR_PRINTABLE(field, text) \
745 TAR_PRINTABLE_EX(field, text, sizeof(h->field))
748 #define TAR_GNU_REGION "[gnu.region]: "
749 #define TAR_GNU_CONTIND "[gnu.contind]: "
752 const char* contind,
bool excpt =
false)
760 if (
memcchr(sparse,
'\0', 24)) {
761 offset = (size_t)(sparse - (
const char*) h);
769 if (ok_off & ok_len) {
803 }
while (sparse < contind);
807 offset = (size_t)(contind - (
const char*) h);
810 + (*contind ?
"\" [to-be-cont'd]" :
"\" [last]");
817 size_t size = bmap.size();
819 for (
size_t n = 0;
n <
size; ++
n) {
847 if (
ok && (ok < 0 || val > 7)) {
850 dump +=
" (base-256)";
857 if (
ok && (ok < 0 || val > 7)) {
860 dump +=
" (base-256)";
867 if (
ok && (ok < 0 || val > 7)) {
870 dump +=
" w/o map(s)!";
873 dump +=
" (base-256)";
899 const char* tname = 0;
906 if (namelen && h->
name[namelen - 1] ==
'/')
907 tname =
"legacy regular entry (directory)";
910 tname =
"legacy regular entry (file)";
917 tname =
"legacy hard link";
919 tname =
"legacy hard link - not FULLY supported";
921 tname += h->
typeflag[0] !=
'\1' ? 7 : 0;
927 tname =
"legacy symbolic link";
929 tname =
"legacy symbolic link - not FULLY supported";
931 tname += h->
typeflag[0] !=
'\2' ? 7 : 0;
937 tname =
"character device";
943 tname =
"block device";
956 tname =
"contiguous file";
959 tname =
"global extended header";
966 tname =
"extended (POSIX 1003.1-2001 [PAX]) header"
967 " - not FULLY supported";
969 tname =
"extended (POSIX 1003.1-2001 [PAX] by Sun) header"
970 " - not FULLY supported";
973 tname =
"extended header";
977 tname =
"Solaris ACL";
981 tname =
"GNU extension: directory dump";
985 tname =
"Solaris extended attribute file";
990 tname =
"Inode metadata only";
995 tname =
"GNU extension: long link";
1001 tname =
"GNU extension: long name";
1007 tname =
"GNU extension: multi-volume entry";
1010 tname =
"STAR extension: multi-volume entry";
1018 tname =
"GNU extension (obsolete): long filename(s)";
1026 tname =
"GNU extension: sparse file";
1031 tname =
"STAR extension: sparse file";
1039 tname =
"Volume header";
1045 tname =
"local vendor enhancement / user-defined extension";
1047 dump += (
" [" +
string(tname ? tname :
"reserved")
1050 :
" -- NOT SUPPORTED]\n"));
1057 tname =
"legacy (V7)";
1061 tname =
"old GNU (NCBI)";
1068 tname =
"ustar (NCBI)";
1075 tname =
"posix (NCBI)";
1106 if (
ok &&
val > 7) {
1113 if (
ok &&
val > 7) {
1122 const char* realsize = h->
star.prefix + 107;
1126 +
"[star.realsize]:\""
1128 if (
ok && (ok < 0 || val > 7)) {
1131 dump +=
" (base-256)";
1144 if (
ok ||
val > 7) {
1160 if (
ok ||
val > 7) {
1169 tname = (
const char*) &h->
star +
sizeof(h->
star);
1178 if (
ok ||
val > 7) {
1194 if (
ok ||
val > 7) {
1210 h->
gnu.contind, excpt);
1211 if (
memcchr(h->
gnu.realsize,
'\0',
sizeof(h->
gnu.realsize))) {
1213 sizeof(h->
gnu.realsize));
1216 if (
ok && (ok < 0 || val > 7)) {
1220 dump +=
" (base-256)";
1223 tname = (
const char*) &h->
gnu +
sizeof(h->
gnu);
1225 tname = h->
gnu.ctime +
sizeof(h->
gnu.ctime);
1239 while (&tname[
n] < (
const char*) h +
BLOCK_SIZE) {
1241 size_t offset = (size_t)(&tname[
n] - (
const char*) h);
1246 const char* e = (
const char*) memchr(&tname[
n],
'\0',
len);
1248 len = (size_t)(e - &tname[
n]);
1262 if (ok < 0 || val > 7 || okaytime) {
1264 if (ok < 0 || val > 7) {
1268 dump +=
"] (base-256)";
1269 }
else if (okaytime) {
1288 #undef TAR_PRINTABLE
1296 ios.setstate(
state);
1309 : m_FileName(filename),
1311 m_Stream(*m_FileStream),
1312 m_ZeroBlockCount(0),
1313 m_BufferSize(
SIZE_OF(blocking_factor)),
1331 m_ZeroBlockCount(0),
1332 m_BufferSize(
SIZE_OF(blocking_factor)),
1364 #define TAR_THROW(who, errcode, message) \
1365 NCBI_THROW(CTarException, errcode, \
1366 s_PositionAsString(who->m_FileName, who->m_StreamPos, \
1367 who->m_BufferSize, \
1368 who->m_Current.GetName()) + (message))
1370 #define TAR_THROW_EX(who, errcode, message, hdr, fmt) \
1371 TAR_THROW(who, errcode, \
1372 who->m_Flags & fDumpEntryHeaders \
1373 ? string(message) + ":\n" + s_DumpHeader(hdr, fmt, true) \
1376 #define TAR_POST(subcode, severity, message) \
1377 ERR_POST_X(subcode, (severity) << \
1378 s_PositionAsString(m_FileName, m_StreamPos, m_BufferSize,\
1379 m_Current.GetName()) + (message))
1386 if (pagesize < 4096 || (pagesize & (pagesize - 1))) {
1389 size_t pagemask = pagesize - 1;
1439 int x_errno = errno;
1443 "Archive flush failed" +
s_OSReason(x_errno));
1446 "Archive flush failed" +
s_OSReason(x_errno));
1459 if (::truncate(filename.c_str(), (off_t) filesize) != 0)
1462 #ifdef NCBI_OS_MSWIN
1464 HANDLE handle = ::CreateFile(x_filename.c_str(), GENERIC_WRITE,
1465 0,
NULL, OPEN_EXISTING,
1466 FILE_ATTRIBUTE_NORMAL,
NULL);
1468 LARGE_INTEGER x_filesize;
1469 x_filesize.QuadPart = filesize;
1470 if (!::SetFilePointerEx(handle, x_filesize,
NULL, FILE_BEGIN)
1471 || !::SetEndOfFile(handle)) {
1472 x_error = (
int) ::GetLastError();
1474 bool closed = ::CloseHandle(handle) ?
true :
false;
1475 if (!x_error && !closed) {
1476 x_error = (
int) ::GetLastError();
1479 x_error = (
int) ::GetLastError();
1491 int x_errno = errno;
1493 "Cannot close archive" +
s_OSReason(x_errno));
1521 }
else if (action !=
eAppend) {
1529 "Pending changes may be discarded"
1530 " upon reopen of in-stream archive");
1538 "Archive I/O stream is in bad state");
1547 #ifdef NCBI_OS_MSWIN
1549 HANDLE handle = (
HANDLE) _get_osfhandle(_fileno(stdin));
1550 if (GetFileType(handle) != FILE_TYPE_DISK) {
1599 int x_errno = errno;
1601 "Cannot open archive" +
s_OSReason(x_errno));
1610 "Archive file is in bad state");
1662 _ASSERT(temp && temp->size() < 2);
1663 if (temp->size() < 1) {
1684 IOS_BASE::iostate iostate =
m_Stream.rdstate();
1686 #ifdef NCBI_COMPILER_MIPSPRO
1693 xread = is->gcount();
1705 # ifdef NCBI_COMPILER_WORKSHOP
1721 + (xread ?
")" :
"): EOF"));
1729 nread += (size_t) xread;
1760 if (!nwrite ||
m_Bad) {
1768 if (avail > nwrite) {
1771 size_t advance = avail;
1772 if (src && src != (
const char*)(-1L)) {
1782 size_t nwritten = 0;
1785 streamsize xwritten;
1786 IOS_BASE::iostate iostate =
m_Stream.rdstate();
1795 if (xwritten <= 0) {
1797 }
else if (iostate) {
1803 if (xwritten <= 0) {
1806 if (src != (
const char*)(-1L)) {
1808 "Archive write failed" +
s_OSReason(x_errno));
1811 "Archive write failed" +
s_OSReason(x_errno));
1814 nwritten += (size_t) xwritten;
1850 const char* p = (
const char*) memchr(
str,
'.',
len);
1853 }
else if (fraq == (
string*)(-1L)) {
1863 if (*p ==
'.' && ++p !=
str +
len) {
1864 len -= (size_t)(p -
str);
1866 for (
size_t n = 0;
n <
len; ++
n) {
1867 if (!
isdigit((
unsigned char) p[
n])) {
1871 if (assign && fraq) {
1872 fraq->assign(p,
len);
1884 for (
size_t i = 0;
i <
len; ++
i) {
1885 unsigned char c = (
unsigned char)
str[
i];
1905 size_t len = fraq.size();
1918 result = (long)((temp + 5) / 10);
1927 Uint8 major = 0, minor = 0,
size = 0, sparse = 0, uid = 0, gid = 0;
1928 Uint8 mtime = 0, atime = 0, ctime = 0,
dummy = 0;
1929 string mtime_fraq, atime_fraq, ctime_fraq;
1930 string path, linkpath, name, uname, gname;
1931 string* nodot = (
string*)(-1L);
1932 const struct SPAXParseTable {
1938 {
"mtime", &mtime, &mtime_fraq,
fPAXMtime },
1939 {
"atime", &atime, &atime_fraq,
fPAXAtime },
1940 {
"ctime", &ctime, &ctime_fraq,
fPAXCtime },
1944 {
"uid", &uid, nodot,
fPAXUid },
1945 {
"gid", &gid, nodot,
fPAXGid },
1948 {
"linkpath", 0, &linkpath,
fPAXNone },
1954 {
"GNU.sparse.realsize", &sparse, nodot,
fPAXSparse },
1955 {
"GNU.sparse.major", &major, nodot,
fPAXSparse },
1956 {
"GNU.sparse.minor", &minor, nodot,
fPAXSparse },
1958 {
"GNU.sparse.name", 0, &name,
fPAXNone },
1960 {
"SCHILY.realsize", &sparse, nodot,
fPAXSparse }
1962 const char* s =
data.c_str();
1964 size_t l =
data.size();
1973 if (!(e = (
char*) memchr(s,
'\n',
l))) {
1977 if (!
isdigit((
unsigned char)(*s)) || !(
len = strtoul(s, &k, 10))
1978 || errno || s +
len - 1 != e || (*k !=
' ' && *k !=
'\t')
1979 || !(v = (
char*) memchr(k,
'=', (
size_t)(e - k)))
1980 || !(klen = (
size_t)(v++ - ++k))
1981 || memchr(k,
' ', klen) || memchr(k,
'\t', klen)
1982 || !(vlen = (
size_t)(e - v))) {
1984 "Skipping malformed PAX data");
1988 for (
size_t n = 0;
n <
sizeof(parser) /
sizeof(parser[0]); ++
n) {
1989 if (strlen(parser[
n].
key) == klen
1990 && memcmp(parser[
n].
key, k, klen) == 0) {
1991 if (!parser[
n].
val) {
1992 if (parser[
n].
str) {
1993 parser[
n].str->assign(v, vlen);
1996 parser[
n].
str, parser[
n].bit)) {
1998 "Ignoring bad numeric \""
2000 +
"\" in PAX value \""
2003 parsed |= parser[
n].bit;
2011 "Ignoring unrecognized PAX value \""
2025 "Ignoring PAX GNU sparse file size "
2027 +
" when real size "
2029 +
" is also present");
2030 }
else if (!
dummy && major == 1 && minor == 0) {
2032 if (!name.empty()) {
2033 if (!path.empty()) {
2035 "Replacing PAX file name \"" + path
2036 +
"\" with GNU sparse file name \"" + name
2044 }
else if (!sparse) {
2071 const string& entryname,
const STarHeader* h,
2082 || !*h->
gnu.contind)
2090 const string& entryname,
const STarHeader* h,
2091 const char* contind,
Uint8 datasize)
2097 +
"GNU sparse file map header (cont'd):\n"
2107 const string& entryname,
2108 const vector< pair<Uint8, Uint8> >& bmap)
2113 +
"PAX GNU/1.0 sparse file map data:\n"
2120 size_t zeroblock_count,
bool eot =
false)
2127 : (eot ?
"End-Of-Tape" :
"End-Of-File")) +
'\n');
2134 return '0' <= c && c <=
'7' ?
true :
false;
2142 size_t nread =
sizeof(block->
buffer);
2149 "Unexpected EOF in archive");
2155 if (memcmp(h->
magic,
"ustar", 6) == 0) {
2156 if ((h->
star.prefix[
sizeof(h->
star.prefix) - 1] ==
'\0'
2164 }
else if (memcmp(h->
magic,
"ustar ", 8) == 0) {
2167 }
else if (memcmp(h->
magic,
"\0\0\0\0\0", 6) == 0) {
2172 "Unrecognized header format", h, fmt);
2182 for (
size_t i = 0;
i <
sizeof(block->
buffer); ++
i) {
2193 "Bad checksum", h, fmt);
2202 unsigned int usum = 0;
2203 const char* p = block->
buffer;
2204 for (
size_t i = 0;
i <
sizeof(block->
buffer); ++
i) {
2206 usum += (
unsigned char)(*p);
2210 for (
size_t j = 0; j <
sizeof(h->
checksum); ++j) {
2212 usum -= (
unsigned char)(*p) -
' ';
2217 if (checksum != ssum && (
unsigned int) checksum != usum) {
2218 string message =
"Header checksum failed";
2220 message +=
", expected ";
2221 if (usum != (
unsigned int) ssum) {
2222 message +=
"either ";
2228 if (usum != (
unsigned int) ssum) {
2230 if ((
unsigned int) ssum > 7) {
2252 ? 107 :
sizeof(h->
star.prefix));
2269 "Bad entry mode", h, fmt);
2277 "Bad user ID", h, fmt);
2285 "Bad group ID", h, fmt);
2293 "Bad entry size", h, fmt);
2299 " This run-time may not support large TAR entries"
2300 " (have you built it --with-lfs?)"
2307 "Bad modification time", h, fmt);
2329 "Bad last access time", h, fmt);
2339 "Bad creation time", h, fmt);
2352 if (namelen && h->
name[namelen - 1] ==
'/') {
2375 "Ignoring hard link size ("
2389 "Bad device minor number", h, fmt);
2391 usum = (
unsigned int)
val;
2394 "Bad device major number", h, fmt);
2401 (
unsigned int)((
val << 16) | usum);
2416 " *** Contiguous TAR entries processed as regular files"
2442 "Repetitious PAX headers,"
2443 " archive may be corrupt");
2463 ? h->
gnu.realsize : h->
star.prefix + 107;
2465 ?
sizeof(h->
gnu.realsize) : 12;
2477 const char* contind = h->
gnu.contind;
2483 "Unexpected EOF in GNU sparse file map"
2484 " extended header");
2487 contind = block->
buffer + (24 * 21);
2507 string(
"Unexpected EOF in ") +
2517 data.append(xbuf, nread);
2535 :
"Long link name: \"")
2551 "Skipping " +
string(
val ?
"empty" :
"zero-sized")
2552 +
" extended header data");
2600 memcpy(block->
buffer +
sizeof(*block) - 4,
"NCBI", 4);
2616 +
"' too long in entry '" + name +
'\'');
2624 +
"' too long in entry '" + name +
'\'');
2641 "Cannot store file mode");
2652 "Cannot store user ID");
2662 "Cannot store group ID");
2673 "Cannot store file size");
2688 "Cannot store modification time");
2691 bool device =
false;
2706 "Cannot store major number");
2711 "Cannot store minor number");
2724 "Do not know how to archive entry '" + name
2726 +
": Internal error");
2733 size_t len = usr.size();
2735 memcpy(h->
uname, usr.c_str(),
len);
2740 memcpy(h->
gname, grp.c_str(),
len);
2751 strcpy(h->
magic,
"ustar");
2756 memcpy(h->
magic,
"ustar ", 8);
2767 "Cannot store checksum");
2783 const char* src = name.c_str();
2784 size_t len = name.size();
2788 memcpy(dst, src,
len);
2792 bool packed =
false;
2793 if (!link &&
len <=
sizeof(h->
prefix) + 1 +
sizeof(h->
name)) {
2799 while (
i > 0 && src[--
i] !=
'/');
2800 if (
i &&
len -
i <=
sizeof(h->
name) + 1) {
2802 memcpy(h->
name, src +
i + 1,
len -
i - 1);
2811 memcpy(dst, src,
size);
2822 strcpy(h->
name,
"././@LongLink");
2833 memcpy(h->
magic,
"ustar ", 8);
2866 "In-stream update may result in gapped tar archive");
2893 "Archive backspace error in record reget");
2904 #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 1101
2909 "Archive backspace error in record reset");
2918 const list<CTempString>& elems,
2923 if (elems.empty()) {
2924 return mask->Match(name, acase);
2926 if (elems.size() == 1) {
2927 return mask->Match(elems.front(), acase);
2931 temp = temp.empty() ?
string(*e) :
string(*e) +
'/' + temp;
2932 if (
mask->Match(temp, acase)) {
2964 "Interspersing zero block ignored");
2988 status !=
eEOF ?
true :
false);
2992 "Orphaned extended information ignored");
2996 "Unexpected EOF in archive");
3000 ?
"Incomplete EOT in archive"
3001 :
"Missing EOT in archive");
3021 "Unused extended header replaced");
3033 || !xinfo.
GetName().empty()) {
3035 "Unused long name \"" + xinfo.
GetName()
3066 if (!xinfo.
GetName().empty()) {
3125 "Ignoring sparse data for non-plain file");
3143 "Empty entry name in archive");
3160 list<CTempString> elems;
3200 #ifdef NCBI_OS_MSWIN
3201 if (
isalpha((
unsigned char) path[0]) && path[1] ==
':') {
3204 }
else if ((path[0] ==
'/' || path[0] ==
'\\') &&
3205 (path[1] ==
'/' || path[1] ==
'\\')) {
3207 path.erase(0, path.find_first_of(
"/\\", 2));
3210 if (path[0] ==
'/' || path[0] ==
'\\') {
3214 path.assign(1,
'.');
3228 #if defined(NCBI_OS_MSWIN)
3232 #elif defined(NCBI_OS_CYGWIN)
3243 if (retval.size() > base_dir.size()) {
3244 retval.erase(0, base_dir.size());
3246 retval.assign(1,
'.');
3251 #ifdef NCBI_OS_MSWIN
3252 if (
isalpha((
unsigned char) retval[0]) && retval[1] ==
':') {
3255 }
else if (retval[0] ==
'/' && retval[1] ==
'/') {
3257 pos = retval.find(
'/', 2);
3264 while (pos < retval.size() && retval[pos] ==
'/') {
3268 retval.erase(0, pos);
3270 pos = retval.size();
3271 while (pos > 0 && retval[pos - 1] ==
'/') {
3274 if (pos < retval.size()) {
3328 size_t len = s.size();
3330 if (s[--
len] !=
'/')
3345 unique_ptr<CDirEntry> dst
3355 unique_ptr<CDirEntry> src;
3362 dst->DereferenceLink();
3375 } extracted = eNotExtracted;
3387 extracted = eConflict;
3398 || memcmp(&dst_stat.
orig.st_dev, &tst_stat.
orig.st_dev,
sizeof(dst_stat.
orig.st_dev)) != 0
3399 || memcmp(&dst_stat.
orig.st_ino, &tst_stat.
orig.st_ino,
sizeof(dst_stat.
orig.st_ino)) != 0) {
3403 extracted = eConflict;
3407 extracted = eMisCase;
3411 extracted = eExtracted;
3437 if (dst_type != src->GetType()) {
3453 "Failed to backup '" + dst->GetPath() +
'\''
3460 if (!(extracted & eConflict)
3470 if ( dst->Exists()) {
3476 if (x_errno != EEXIST || !link) {
3478 "Cannot extract '" + dst->GetPath() +
'\''
3483 "Cannot create " + whatlink +
" '" + dst->GetPath() +
"' -> '"
3491 "Cannot extract '" + dst->GetPath() +
'\''
3499 umask(u & ~(S_IRUSR | S_IWUSR | S_IXUSR));
3515 }
else if (pending && !pending->Restore()) {
3518 "Cannot restore '" + dst->GetPath()
3524 unique_ptr<CDirEntry> dst
3542 #ifndef NCBI_COMPILER_WORKSHOP
3550 if (
m_Stream.rdbuf()->PUBSEEKOFF(fskip, IOS_BASE::cur)
3558 "Cannot fast skip in file archive,"
3559 " reverting to slow skip");
3570 "Archive skip failed (EOF)");
3586 unique_ptr<CDirEntry> src_ptr;
3587 bool extracted =
true;
3604 "Cannot create directory '" + dir.
GetPath() +
'\''
3614 src = src_ptr.get();
3632 int x_errno = errno;
3633 if (x_errno == ENOENT || x_errno == EEXIST || x_errno == ENOTDIR) {
3637 "Cannot hard link '" + dst->
GetPath()
3638 +
"' -> '" + src->
GetPath() +
'\''
3640 + (extracted ?
", trying to copy" :
""));
3650 "Cannot hard link '" + dst->
GetPath()
3651 +
"' -> '" + src->
GetPath() +
"' via copy"
3673 const CDir* dir =
dynamic_cast<const CDir*
>(dst);
3677 "Cannot create directory '" + dst->
GetPath() +
'\''
3679 ?
string(
": Internal error")
3693 string error =
"Cannot create symlink '" + dst->
GetPath()
3696 ?
string(
": Internal error")
3698 if (!symlink || x_errno != ENOTSUP
3716 int x_errno = errno;
3719 int x_errno = ENOTSUP;
3721 string reason =
": Feature not supported by host OS";
3725 =
"Cannot create FIFO '" + dst->
GetPath() +
'\'' + reason;
3744 int x_errno = errno;
3747 int x_errno = ENOTSUP;
3749 string reason =
": Feature not supported by host OS";
3754 ?
"character" :
"block")
3755 +
" device '" + dst->
GetPath() +
'\'' + reason;
3796 int x_errno = errno;
3798 "Cannot create file '" + dst->
GetPath() +
'\''
3806 bool okay = ofs.good();
3807 if (okay)
while (
size) {
3813 "Unexpected EOF in archive");
3818 okay = ofs.write(
data, (streamsize) nread) ?
true :
false;
3830 if (!okay || !ofs.good()) {
3831 int x_errno = errno;
3833 "Cannot " +
string(okay ?
"close" :
"write")
3844 for (
n = 0;
n < nread; ++
n) {
3849 line.append(
data,
n);
3851 if (
data[
n] ==
'\n') {
3865 if (
size >= nread) {
3883 #ifdef NCBI_OS_MSWIN
3884 # define NCBI_FILE_WO "wb"
3886 # define NCBI_FILE_WO "w"
3899 "Unexpected EOF in archive");
3902 if (
size >= nread) {
3914 "Cannot expand sparse file '" + dst->
GetPath()
3915 +
"': Region count is "
3916 +
string(num.empty() ?
"missing" :
"invalid")
3917 +
" (\"" + num +
"\")");
3922 vector< pair<Uint8, Uint8> > bmap(
n);
3926 for (
int k = 0; k < 2; ++k) {
3932 "Cannot expand sparse file '" + dst->
GetPath()
3934 +
string(k == 0 ?
"offset" :
"region size")
3936 +
string(num.empty() ?
"missing" :
"invalid")
3937 +
" (\"" + num +
"\")");
3941 bmap[
i] = pair<Uint8, Uint8>(
val[0],
val[1]);
3952 int x_errno = errno;
3954 "Cannot create file '" + dst->
GetPath() +
'\''
3966 Uint8 top = bmap[
i].first + bmap[
i].second;
3970 if (!bmap[
i].second) {
3975 if (!(x_error = errno))
3988 "Cannot read archive data for sparse file '"
3989 + dst->
GetPath() +
"', region #"
3993 :
string(
": End-of-data")));
4002 size_t xread = nread;
4003 if (xread > bmap[
i].second -
done) {
4004 xread = (size_t)(bmap[
i].second -
done);
4006 if (::fwrite(
data, 1, xread,
fp.get()) != xread) {
4007 if (!(x_error = errno)) {
4015 }
while (
done < bmap[
i].second);
4022 bool closed = ::fclose(
fp.release()) == 0 ?
true :
false;
4023 if (!x_error && !closed) {
4024 if (!(x_error = errno))
4033 #ifdef NCBI_OS_MSWIN
4035 DWORD rv = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
4036 FORMAT_MESSAGE_FROM_SYSTEM |
4037 FORMAT_MESSAGE_MAX_WIDTH_MASK |
4038 FORMAT_MESSAGE_IGNORE_INSERTS,
4040 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
4047 ::LocalFree((HLOCAL)
str);
4049 if (reason.empty()) {
4063 "Cannot write sparse file '" + dst->
GetPath() +
'\''+ reason);
4078 unique_ptr<CDirEntry> path_ptr;
4081 path = path_ptr.get();
4089 CTime modification(
info.GetModificationTime());
4090 CTime last_access(
info.GetLastAccessTime());
4095 if (!path->
SetTime(&modification, &last_access, &creation)) {
4098 "Cannot restore date/time for '" + path->
GetPath() +
'\''
4112 if (!
info.GetUserName().empty() || !
info.GetGroupName().empty()) {
4113 unsigned int uid, gid;
4116 || (!
info.GetGroupName().empty()
4119 || (uid ==
info.GetUserId() && gid ==
info.GetGroupId())) {
4147 if (
mode & (S_ISUID | S_ISGID)) {
4148 mode &= ~(S_ISUID | S_ISGID);
4160 s_TarToMode(perm, &user, &group, &other, &special_bits);
4162 info.GetMode(&user, &group, &other, &special_bits);
4169 "Cannot " +
string(perm ?
"change" :
"restore")
4170 +
" permissions for '" + path->
GetPath() +
'\''
4180 #ifdef NCBI_OS_MSWIN
4194 unique_ptr<CDir::TEntries> dir;
4198 unsigned int uid = 0, gid = 0;
4211 if (!entry.
Stat(&
st, follow_links)) {
4212 int x_errno = errno;
4214 "Cannot get status of '" + path +
'\''+
s_OSReason(x_errno));
4222 "Empty entry name not allowed");
4225 list<CTempString> elems;
4228 if (find(elems.begin(), elems.end(),
"..") != elems.end()) {
4230 "Name '" + temp +
"' embeds parent directory (\"..\")");
4250 "Empty link name not allowed");
4255 follow_links, &uid, &gid);
4264 #ifdef NCBI_OS_MSWIN
4266 st.orig.st_uid = (uid_t) uid;
4267 st.orig.st_gid = (gid_t) gid;
4284 const string* entry_path_ptr;
4285 if (e->GetPath().empty()) {
4287 entry_path_ptr = &entry_path;
4289 entry_path_ptr = &e->GetPath();
4291 if (!temp.empty()) {
4293 temp != *entry_path_ptr) {
4296 }
else if (path == *entry_path_ptr) {
4314 <= e->GetModificationCTime()) {
4352 "Cannot list directory '" + path +
'\'' +
s_OSReason(x_errno);
4368 unique_ptr<TEntries> add =
x_Append((*e)->GetPath(), toc);
4378 "Skipping non-archiveable "
4380 +
" '" + path +
'\'');
4387 "Unable to archive '" + path +
'\'');
4396 "Skipping unsupported source '" + path
4421 temp.resize(temp.size() - 1);
4425 "Empty entry name not allowed");
4428 list<CTempString> elems;
4431 if (find(elems.begin(), elems.end(),
"..") != elems.end()) {
4433 "Name '" + temp +
"' embeds parent directory (\"..\")");
4445 "Bad input file stream");
4463 # ifdef HAVE_GETUMASK
4481 #ifdef NCBI_OS_MSWIN
4486 unsigned int uid = 0, gid = 0;
4519 avail = (size_t)
size;
4530 xread = is.gcount();
4539 ifstream* ifs =
dynamic_cast<ifstream*
>(&is);
4542 +
string(ifs ?
"file" :
"stream")
4546 avail = (size_t) xread;
4571 int x_errno = errno;
4590 if (idx < 0 ||
sizeof(
m_Mask)/
sizeof(
m_Mask[0]) <= (
size_t) idx){
4611 size_t blocking_factor,
4612 const string& base_dir)
4614 const size_t buffer_size =
SIZE_OF(blocking_factor);
4625 size_t namelen = name.size() + 1;