tôi figured này ra bản thân mình sau một chút công việc. tar file spec thực sự cho bạn biết mọi thứ bạn cần biết. Trước hết, mỗi tập tin bắt đầu với tiêu đề 512 byte, vì vậy bạn có thể biểu diễn nó bằng một ký tự char [512] hoặc char * trỏ vào vị trí nào đó trong mảng char lớn hơn của bạn (nếu bạn có toàn bộ tệp được tải vào một mảng). ví dụ).
Phần header trông như thế này:
location size field
0 100 File name
100 8 File mode
108 8 Owner's numeric user ID
116 8 Group's numeric user ID
124 12 File size in bytes
136 12 Last modification time in numeric Unix time format
148 8 Checksum for header block
156 1 Link indicator (file type)
157 100 Name of linked file
Vì vậy, nếu bạn muốn tên tập tin, bạn lấy nó ngay tại đây với string filename(buffer[0], 100);
. Tên tập tin là rỗng đệm, vì vậy bạn có thể làm một kiểm tra để đảm bảo có ít nhất một null và sau đó để lại kích thước nếu bạn muốn tiết kiệm không gian.
Bây giờ, chúng tôi muốn biết đó là tệp hay thư mục. Trường "chỉ báo liên kết" có thông tin này, vì vậy:
// Note that we're comparing to ascii numbers, not ints
switch(buffer[156]){
case '0': // intentionally dropping through
case '\0':
// normal file
break;
case '1':
// hard link
break;
case '2':
// symbolic link
break;
case '3':
// device file/special file
break;
case '4':
// block device
break;
case '5':
// directory
break;
case '6':
// named pipe
break;
}
Tại thời điểm này, chúng tôi đã có tất cả thông tin cần thiết về thư mục nhưng chúng tôi cần thêm một thông tin từ các tệp thông thường.
Độ dài của tệp có thể được lưu trữ theo hai cách khác nhau, dưới dạng chuỗi bát phân kết thúc bằng 0 hoặc không gian đệm hoặc "mã cơ sở 256 được chỉ định bằng cách đặt bit thứ tự cao của byte ngoài cùng bên trái của trường số ".
Giá trị số được mã hóa bằng số bát phân sử dụng các số ASCII, với số 0 đứng đầu. Vì lý do lịch sử, nên sử dụng ký tự NUL hoặc dấu cách cuối cùng. Do đó, mặc dù có 12 byte dành riêng để lưu trữ kích thước tệp, chỉ có thể lưu 11 số bát phân.Điều này cho phép kích thước tệp tối đa là 8 gigabyte trên các tệp được lưu trữ. Để khắc phục hạn chế này, ngôi sao năm 2001 đã giới thiệu mã hóa cơ bản 256 được chỉ định bằng cách thiết lập bit thứ tự cao của byte tận cùng bên trái của một trường số. GNU-tar và BSD-tar theo ý tưởng này. Ngoài ra, các phiên bản của tar từ trước tiêu chuẩn POSIX đầu tiên từ 1988 pad các giá trị có dấu cách thay vì số không.
Đây là cách bạn sẽ đọc các định dạng bát phân, nhưng tôi đã không viết mã cho phiên bản cơ sở-256:
// in one function
int size_of_file = octal_string_to_int(&buffer[124], 11);
// elsewhere
int octal_string_to_int(char *current_char, unsigned int size){
unsigned int output = 0;
while(size > 0){
output = output * 8 + *current_char - '0';
current_char++;
size--;
}
return output;
}
Ok, vì vậy bây giờ chúng tôi có tất cả mọi thứ ngoại trừ các nội dung tập tin thực tế. Tất cả chúng ta phải làm là lấy size
byte tiếp theo của dữ liệu từ tập tin tar và chúng tôi sẽ có những nội dung tập tin của chúng tôi:
// Get to the next block after the header ends
location += 512;
file_contents = new char[size];
memcpy(file_contents, &buffer[location], size);
// Go to the next block by rounding up to 512
// This isn't necessarily the most efficient way to do this,
// but it's the most obvious.
location += (int)ceil(size/512.0)
'man tar' cho tôi biết' -t Liệt kê nội dung lưu trữ để stdout.' Đó có phải là những gì bạn muốn không? – Potatoswatter
Điều tôi thực sự muốn là ngược lại: đọc một tập tin tar từ stdin. –