Changeset View
Changeset View
Standalone View
Standalone View
src/ktar.cpp
Show First 20 Lines • Show All 190 Lines • ▼ Show 20 Line(s) | 187 | { | |||
---|---|---|---|---|---|
191 | // and the prefix can have a value and in this case we don't reset n. | 191 | // and the prefix can have a value and in this case we don't reset n. | ||
192 | if (n == 0x200 && (buffer[0] != 0 || buffer[0x159] != 0)) { | 192 | if (n == 0x200 && (buffer[0] != 0 || buffer[0x159] != 0)) { | ||
193 | // Make sure this is actually a tar header | 193 | // Make sure this is actually a tar header | ||
194 | if (strncmp(buffer + 257, "ustar", 5)) { | 194 | if (strncmp(buffer + 257, "ustar", 5)) { | ||
195 | // The magic isn't there (broken/old tars), but maybe a correct checksum? | 195 | // The magic isn't there (broken/old tars), but maybe a correct checksum? | ||
196 | 196 | | |||
197 | int check = 0; | 197 | int check = 0; | ||
198 | for (uint j = 0; j < 0x200; ++j) { | 198 | for (uint j = 0; j < 0x200; ++j) { | ||
199 | check += buffer[j]; | 199 | check += static_cast<unsigned char>(buffer[j]); | ||
200 | } | 200 | } | ||
201 | 201 | | |||
202 | // adjust checksum to count the checksum fields as blanks | 202 | // adjust checksum to count the checksum fields as blanks | ||
203 | for (uint j = 0; j < 8 /*size of the checksum field including the \0 and the space*/; j++) { | 203 | for (uint j = 0; j < 8 /*size of the checksum field including the \0 and the space*/; j++) { | ||
204 | check -= buffer[148 + j]; | 204 | check -= static_cast<unsigned char>(buffer[148 + j]); | ||
205 | } | 205 | } | ||
206 | check += 8 * ' '; | 206 | check += 8 * ' '; | ||
207 | 207 | | |||
208 | QByteArray s = QByteArray::number(check, 8); // octal | 208 | QByteArray s = QByteArray::number(check, 8); // octal | ||
209 | 209 | | |||
210 | // only compare those of the 6 checksum digits that mean something, | 210 | // only compare those of the 6 checksum digits that mean something, | ||
211 | // because the other digits are filled with all sorts of different chars by different tars ... | 211 | // because the other digits are filled with all sorts of different chars by different tars ... | ||
212 | // Some tars right-justify the checksum so it could start in one of three places - we have to check each. | 212 | // Some tars right-justify the checksum so it could start in one of three places - we have to check each. | ||
▲ Show 20 Lines • Show All 480 Lines • ▼ Show 20 Line(s) | 645 | { | |||
693 | // user | 693 | // user | ||
694 | strcpy(buffer + 0x109, uname); | 694 | strcpy(buffer + 0x109, uname); | ||
695 | // group | 695 | // group | ||
696 | strcpy(buffer + 0x129, gname); | 696 | strcpy(buffer + 0x129, gname); | ||
697 | 697 | | |||
698 | // Header check sum | 698 | // Header check sum | ||
699 | int check = 32; | 699 | int check = 32; | ||
700 | for (uint j = 0; j < 0x200; ++j) { | 700 | for (uint j = 0; j < 0x200; ++j) { | ||
701 | check += buffer[j]; | 701 | check += static_cast<unsigned char>(buffer[j]); | ||
702 | } | 702 | } | ||
703 | s = QByteArray::number(check, 8); // octal | 703 | s = QByteArray::number(check, 8); // octal | ||
704 | s = s.rightJustified(6, '0'); | 704 | s = s.rightJustified(6, '0'); | ||
705 | memcpy(buffer + 0x94, s.constData(), 6); | 705 | memcpy(buffer + 0x94, s.constData(), 6); | ||
706 | } | 706 | } | ||
707 | 707 | | |||
708 | void KTar::KTarPrivate::writeLonglink(char *buffer, const QByteArray &name, char typeflag, | 708 | void KTar::KTarPrivate::writeLonglink(char *buffer, const QByteArray &name, char typeflag, | ||
709 | const char *uname, const char *gname) | 709 | const char *uname, const char *gname) | ||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Line(s) | 767 | if ((mode() & QIODevice::ReadWrite) == QIODevice::ReadWrite) { | |||
768 | device()->seek(d->tarEnd); // Go to end of archive as might have moved with a read | 768 | device()->seek(d->tarEnd); // Go to end of archive as might have moved with a read | ||
769 | } | 769 | } | ||
770 | 770 | | |||
771 | // provide converted stuff we need later on | 771 | // provide converted stuff we need later on | ||
772 | const QByteArray encodedFileName = QFile::encodeName(fileName); | 772 | const QByteArray encodedFileName = QFile::encodeName(fileName); | ||
773 | const QByteArray uname = user.toLocal8Bit(); | 773 | const QByteArray uname = user.toLocal8Bit(); | ||
774 | const QByteArray gname = group.toLocal8Bit(); | 774 | const QByteArray gname = group.toLocal8Bit(); | ||
775 | 775 | | |||
776 | // If more than 100 chars, we need to use the LongLink trick | 776 | // If more than 100 bytes, we need to use the LongLink trick | ||
777 | if (fileName.length() > 99) { | 777 | if (encodedFileName.length() > 99) { | ||
cfeck: Does the spec say `> 99` or `> 100`? The comment and the code should match. | |||||
The comment is right in some sense, 100 bytes means 99 bytes of name and 1 byte of '\0'. I don't know for sure if there is a (single) spec actually. At least GNU tar (http://www.gnu.org/software/tar/manual/html_node/Standard.html) mentions that although name[100] is a 100-byte field, "The name, linkname, magic, uname, and gname are null-terminated character strings." So, there could be string of at most 99 bytes, plus a zero-terminator. However, there is a special case in this source file where 100-byte but non-zero-terminated names are handled (search for "bug:101472" string in the source). Maybe, there are such tar files in the wild. How should I change the comment? ibragimovrinat: The comment is right in some sense, 100 bytes means 99 bytes of name and 1 byte of '\0'.
I… | |||||
778 | d->writeLonglink(buffer, encodedFileName, 'L', uname.constData(), gname.constData()); | 778 | d->writeLonglink(buffer, encodedFileName, 'L', uname.constData(), gname.constData()); | ||
779 | } | 779 | } | ||
780 | 780 | | |||
781 | // Write (potentially truncated) name | 781 | // Write (potentially truncated) name | ||
782 | strncpy(buffer, encodedFileName.constData(), 99); | 782 | strncpy(buffer, encodedFileName.constData(), 99); | ||
783 | buffer[99] = 0; | 783 | buffer[99] = 0; | ||
784 | // zero out the rest (except for what gets filled anyways) | 784 | // zero out the rest (except for what gets filled anyways) | ||
785 | memset(buffer + 0x9d, 0, 0x200 - 0x9d); | 785 | memset(buffer + 0x9d, 0, 0x200 - 0x9d); | ||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Line(s) | 832 | if ((mode() & QIODevice::ReadWrite) == QIODevice::ReadWrite) { | |||
833 | device()->seek(d->tarEnd); // Go to end of archive as might have moved with a read | 833 | device()->seek(d->tarEnd); // Go to end of archive as might have moved with a read | ||
834 | } | 834 | } | ||
835 | 835 | | |||
836 | // provide converted stuff we need lateron | 836 | // provide converted stuff we need lateron | ||
837 | QByteArray encodedDirname = QFile::encodeName(dirName); | 837 | QByteArray encodedDirname = QFile::encodeName(dirName); | ||
838 | QByteArray uname = user.toLocal8Bit(); | 838 | QByteArray uname = user.toLocal8Bit(); | ||
839 | QByteArray gname = group.toLocal8Bit(); | 839 | QByteArray gname = group.toLocal8Bit(); | ||
840 | 840 | | |||
841 | // If more than 100 chars, we need to use the LongLink trick | 841 | // If more than 100 bytes, we need to use the LongLink trick | ||
842 | if (dirName.length() > 99) { | 842 | if (encodedDirname.length() > 99) { | ||
843 | d->writeLonglink(buffer, encodedDirname, 'L', uname.constData(), gname.constData()); | 843 | d->writeLonglink(buffer, encodedDirname, 'L', uname.constData(), gname.constData()); | ||
844 | } | 844 | } | ||
845 | 845 | | |||
846 | // Write (potentially truncated) name | 846 | // Write (potentially truncated) name | ||
847 | strncpy(buffer, encodedDirname.constData(), 99); | 847 | strncpy(buffer, encodedDirname.constData(), 99); | ||
848 | buffer[99] = 0; | 848 | buffer[99] = 0; | ||
849 | // zero out the rest (except for what gets filled anyways) | 849 | // zero out the rest (except for what gets filled anyways) | ||
850 | memset(buffer + 0x9d, 0, 0x200 - 0x9d); | 850 | memset(buffer + 0x9d, 0, 0x200 - 0x9d); | ||
Show All 38 Lines | 869 | { | |||
889 | } | 889 | } | ||
890 | 890 | | |||
891 | // provide converted stuff we need lateron | 891 | // provide converted stuff we need lateron | ||
892 | QByteArray encodedFileName = QFile::encodeName(fileName); | 892 | QByteArray encodedFileName = QFile::encodeName(fileName); | ||
893 | QByteArray encodedTarget = QFile::encodeName(target); | 893 | QByteArray encodedTarget = QFile::encodeName(target); | ||
894 | QByteArray uname = user.toLocal8Bit(); | 894 | QByteArray uname = user.toLocal8Bit(); | ||
895 | QByteArray gname = group.toLocal8Bit(); | 895 | QByteArray gname = group.toLocal8Bit(); | ||
896 | 896 | | |||
897 | // If more than 100 chars, we need to use the LongLink trick | 897 | // If more than 100 bytes, we need to use the LongLink trick | ||
898 | if (target.length() > 99) { | 898 | if (encodedTarget.length() > 99) { | ||
899 | d->writeLonglink(buffer, encodedTarget, 'K', uname.constData(), gname.constData()); | 899 | d->writeLonglink(buffer, encodedTarget, 'K', uname.constData(), gname.constData()); | ||
900 | } | 900 | } | ||
901 | if (fileName.length() > 99) { | 901 | if (encodedFileName.length() > 99) { | ||
902 | d->writeLonglink(buffer, encodedFileName, 'L', uname.constData(), gname.constData()); | 902 | d->writeLonglink(buffer, encodedFileName, 'L', uname.constData(), gname.constData()); | ||
903 | } | 903 | } | ||
904 | 904 | | |||
905 | // Write (potentially truncated) name | 905 | // Write (potentially truncated) name | ||
906 | strncpy(buffer, encodedFileName.constData(), 99); | 906 | strncpy(buffer, encodedFileName.constData(), 99); | ||
907 | buffer[99] = 0; | 907 | buffer[99] = 0; | ||
908 | // Write (potentially truncated) symlink target | 908 | // Write (potentially truncated) symlink target | ||
909 | strncpy(buffer + 0x9d, encodedTarget.constData(), 99); | 909 | strncpy(buffer + 0x9d, encodedTarget.constData(), 99); | ||
Show All 20 Lines |
Does the spec say > 99 or > 100? The comment and the code should match.