@@ -33,10 +33,24 @@ length = i; return [OFString stringWithUTF8String: buffer length: length]; } + +static void +stringToBuffer(unsigned char *buffer, OFString *string, size_t length) +{ + size_t UTF8StringLength = [string UTF8StringLength]; + + if (UTF8StringLength > length) + @throw [OFOutOfRangeException exception]; + + memcpy(buffer, [string UTF8String], UTF8StringLength); + + for (size_t i = UTF8StringLength; i < length; i++) + buffer[i] = '\0'; +} static uintmax_t octalValueFromBuffer(const char *buffer, size_t length, uintmax_t max) { uintmax_t value = [stringFromBuffer(buffer, length) octalValue]; @@ -241,6 +255,52 @@ objc_autoreleasePoolPop(pool); return [ret autorelease]; } + +- (void)of_writeToStream: (OFStream *)stream +{ + unsigned char buffer[512]; + uint64_t modificationDate; + uint16_t checksum = 0; + + stringToBuffer(buffer, _fileName, 100); + stringToBuffer(buffer + 100, + [OFString stringWithFormat: @"%06" PRIo32 " ", _mode], 8); + memcpy(buffer + 108, "000000 \0" "000000 \0", 16); + stringToBuffer(buffer + 124, + [OFString stringWithFormat: @"%011" PRIo64 " ", _size], 12); + modificationDate = [_modificationDate timeIntervalSince1970]; + stringToBuffer(buffer + 136, + [OFString stringWithFormat: @"%011" PRIo64 " ", modificationDate], + 12); + + /* + * During checksumming, the checksum field is expected to be set to 8 + * spaces. + */ + memset(buffer + 148, ' ', 8); + + buffer[156] = _type; + stringToBuffer(buffer + 157, _targetFileName, 100); + + /* ustar */ + memcpy(buffer + 257, "ustar\0" "00", 8); + stringToBuffer(buffer + 265, _owner, 32); + stringToBuffer(buffer + 297, _group, 32); + stringToBuffer(buffer + 329, + [OFString stringWithFormat: @"%06" PRIo32 " ", _deviceMajor], 8); + stringToBuffer(buffer + 337, + [OFString stringWithFormat: @"%06" PRIo32 " ", _deviceMinor], 8); + memset(buffer + 345, '\0', 155 + 12); + + /* Fill in the checksum */ + for (size_t i = 0; i < 500; i++) + checksum += buffer[i]; + stringToBuffer(buffer + 148, + [OFString stringWithFormat: @"%06" PRIo16, checksum], 7); + + [stream writeBuffer: buffer + length: sizeof(buffer)]; +} @end