/* Do not remove the headers from this file! see /USAGE for more info. */ /* ** Posix tar object in LPC. Zellski, zell@alyx.com, 1996. ** ** Written for Igor Mud, a DGD-based 2.4.5. Should be fairly ** portable -- does need mutable, non-zero-sensitive strings. ** ** Anybody is free to do anything with this code as far as I ** am concerned. Of course, I also consider myself free to call ** people bloody bastards when they are. ** ** MudOS port by Beek */ # define FILES_PER_SECOND 10 # define LF_DIR 5 # define LF_NORMAL 0 /* change these any way your lil' hearts desire */ # define UID 1701 # define GID 2261 # define UNAME to_buffer("zell") # define GNAME to_buffer("alyx") buffer to_buffer(mixed arg) { buffer ret; if (intp(arg)) arg = arg + ""; if (stringp(arg)) { ret = allocate_buffer(strlen(arg)); write_buffer(ret, 0, arg); } return ret; } void header_insert(buffer what, int offset, int size); #define null_record allocate_buffer(0x200) buffer header_record; void tar(string dir, string archive) { rm(archive); call_out("add_next_files", 0, ({ dir }), archive); } buffer octal(int num, int width) { buffer result; int i; result = null_record; i = width; result[-- i] = ' '; do { result[-- i] = '0' + (num & 0x07); num >>= 3; } while (num != 0); while (i > 0) result[-- i] = ' '; return result[0 .. width-1]; } void header_insert(buffer what, int offset, int size) { int i, mid, end; if (sizeof(what) > size) { what = what[0 .. size-1]; } mid = offset + sizeof(what); end = offset + size; header_record[offset..mid-1] = what; if (end - mid) header_record[mid..end-1] = allocate_buffer(end - mid); } void write_header(string archive, string name, int size, int type) { buffer str; int sum; int i; header_insert(to_buffer(name), 0x00, 0x64); header_insert(octal(size, 12), 0x7C, 0x0C); header_insert(octal(time(), 12), 0x88, 0x0C); header_insert(to_buffer(type), 0x9C, 0x01); header_insert(to_buffer(" "), 0x94, 0x08); for (i = 0; i < 0x200; i ++) { sum += header_record[i]; } str = octal(sum, 7)[0..<2] + allocate_buffer(2); str[7] = ' '; /* tar SUCKS */ header_insert(str, 0x94, 0x08); write_buffer(archive, file_size(archive), header_record); } void add_next_files(string *files, string archive) { int count; for (count = 0; count < FILES_PER_SECOND; count ++) { if (file_size(files[0]) == -2) { /* a directory: descend and push contents onto stackish thing */ int i; string *contents; contents = get_dir(files[0] + "/"); for (i = 0; i < sizeof(contents); i ++) { contents[i] = files[0] + "/" + contents[i]; } write_header(archive, files[0] + "/", 0, LF_DIR); files = contents + files[1 ..]; } else { if (files[0] != archive) { int i, size; /* don't include archive in archive :) */ size = file_size(files[0]); write(files[0] + "\t (" + size + ") : "); if (size > 0) { write_header(archive, files[0], size, LF_NORMAL); /* write all full records first */ for (i = 0; i < (size & 0xFFFE00); i += 0x200) { string data; data = read_buffer(files[0], i, 0x200); if (!data) { error("failed to read 512 bytes from " + files[0]); } write_buffer(archive, file_size(archive), data); } /* pad last record, if anything left to write */ if (size % 0x200) { buffer data; data = read_buffer(files[0], i, size % 0x200) + null_record; if (!data) { error("failed to read " + (size % 0x200) + " bytes from " + files[0]); } write_buffer(archive, file_size(archive), data[0 .. 0x1FF]); /* write 512 bytes */ } write("done.\n"); } else { write("skipped.\n"); } } files = files[1 ..]; if (!sizeof(files)) { write("DONE.\n"); return; } } } call_out("add_next_files", 1, files, archive); } void create() { header_record = null_record; header_insert(to_buffer("ustar "), 0x101, 0x08); /* POSIX-tar magic */ header_insert(to_buffer(" 40755 "), 0x64, 0x08); header_insert(octal(UID, 7),0x6C, 0x08); header_insert(octal(GID, 7),0x74, 0x08); header_insert(UNAME, 0x109, 0x20); header_insert(GNAME, 0x129, 0x20); }