/* TAR extractor for LPC. This object is a crude tape archive extractor Its basic use is to allow wizards to extract a single tar file if you allow some sought of ftp daemon. This will not allow the overwriting of files. Access priviledges are based on this_player() as a call_out() is used (so this_interactive() == 0). So access would be limited to open directories, and the wizards directory (ie if they use the standard access object). This will also apply to the tar file. Zilanthius (c) 1994 */ #include <mudlib.h> inherit TREASURE; #define BLOCK_SIZE 512 #define MAX_BUFFER 500 /* lines */ string root_dir; /* current working directory */ string tar_file; /* tar file */ int f_ptr; /* current positon in tar file */ string current_file; /* current file being extracted */ int current_file_length; /* length of buffer that is yet to be read */ int current_file_size; /* file size */ string buffer; /* text buffer */ status fatal; /* exit if error has occured */ status in_use; /* currently extracting */ status buffer_eof; /* buffer has read EOF */ status is_file; /* file already exists */ static void buffer_to_file(); void reset(status arg) { if(arg) return; set_short("Tarx"); set_name("tarx"); } void init() { ::init(); add_action("tarx", "tarx"); } /* convert octal to integer */ int oct_to_int(int oct) { int i, base; for(base = 1, i = 0; oct; base *= 8) { i += (oct - (oct/10) * 10) * base; oct /= 10; } return i; } /* fill text buffer */ static void fill_buffer() { if(!(buffer = read_file(tar_file,f_ptr,MAX_BUFFER))) { write("Error reading tar file.\n"); fatal = 1; return; } #ifdef OLD_EXPLODE if(sizeof(explode(buffer +"\n","\n")) - 1 != MAX_BUFFER) buffer_eof = 1; #else if(sizeof(explode(buffer,"\n")) - 1 != MAX_BUFFER) buffer_eof = 1; #endif f_ptr += MAX_BUFFER; } /* retrieve file, file size and start text from txt header */ status filter_modes(string str) { return str != ""; } #define FILE_NAME 0 #define FILE_SIZE 4 #define FILE_MODE 7 static void interpret_header() { string mode_str, *file_modes, rest; string str1, str2, str3; int i, field, mode, flag; if(fatal || !buffer || buffer == "") return; /* basic header format */ if(sscanf(buffer,"%s ustar %s", mode_str, rest) != 2) { if(buffer_eof) write("Ok\n"); else write("Error: Header incorrect format.\n"); fatal = 1; return; } /* get file mode, file size, file name */ #ifdef OLD_EXPLODE file_modes = explode(mode_str +" "," "); #else file_modes = explode(mode_str," "); #endif file_modes = filter_array(file_modes,"filter_modes",this_object()); if(sizeof(file_modes) != 8) { write("Error: Incorrect mode string.\n"); for(i = 0; i < sizeof(file_modes); i++) { write("\tMode"+ i +": "+ file_modes[i] +"\n"); } fatal = 1; return; } /* file name */ current_file = file_modes[FILE_NAME]; /* file size */ if(!sscanf(file_modes[FILE_SIZE],"%d",current_file_length)) { write("Error: Cannot retrieve file size.\n"); fatal = 1; } current_file_length = oct_to_int(current_file_length); current_file_size = current_file_length; #if 0 /* file mode */ if(!sscanf(file_modes[FILE_MODE],"%d",mode)) { write("Error: Cannot retrieve file mode.\n"); fatal = 1; } if(mode != 0 && mode != 5) { write("Error: Illegal file mode.\n"); fatal = 1; } #endif /* strip header */ if(sscanf(buffer,"%s"+ current_file +"%s", str1, buffer) == 2) { buffer = current_file + buffer; } buffer = extract(buffer,BLOCK_SIZE); } static void tar_extract() { int max_loop; while(!fatal && buffer) { if(max_loop++ > 15) { write("Continuing Tarx....\n"); call_out("tar_extract",1); return; } interpret_header(); if(!fatal) { is_file = (file_size(root_dir + current_file) >= 0) ? 1 : 0; buffer_to_file(); } } in_use = 0; } void buffer_to_file() { string txt, str; int i; if(!current_file_length || current_file[strlen(current_file)-1] == '/') { if(current_file[strlen(current_file)-1] == '/') { current_file = extract(current_file,0,strlen(current_file)-2); } if(file_size(root_dir + current_file) == -2 || mkdir(root_dir + current_file)) { str = current_file; str += " "; str = extract(str,0,55) +" Directory\n"; write(str); log_file("TARX", str); } else { fatal = 1; write("Error: Cannot create directory "+ root_dir + current_file +"\n"); } } else { txt = extract(buffer,0,current_file_length-1); while (!fatal && strlen(txt) < current_file_length) { if(!is_file) write_file(root_dir + current_file,buffer); current_file_length -= strlen(buffer); fill_buffer(); txt = extract(buffer,0,current_file_length-1); } if(!is_file) write_file(root_dir + current_file, txt); str = current_file; str += " "; str = extract(str,0,55) +" File "; if(is_file) { str += "exists\n"; } else { i = 1 + current_file_size/BLOCK_SIZE; str += "\t"+ i; if(i <= 999) str += " "; if(i <= 99) str += " "; if(i <= 9) str += " "; str += " Blocks\n"; } write(str); log_file("TARX", str); buffer = extract(buffer,current_file_length); } } /* action */ status tarx(string str) { string file; if(in_use) { notify_fail("Currently extracting "+ tar_file +"\n"); return 0; } if(!str) { notify_fail("tarx <file>, extracts tar file into current directory\n"); return 0; } tar_file = (string)this_player()->make_path(str); if(file_size(tar_file) <= 0) { notify_fail(str +" does not exist.\n"); return 0; } write("Zilanthius' Tar Extractor (c) 1994\n\n"); root_dir = (string)this_player()->query_path() +"/"; if(root_dir[0] != '/') root_dir = "/"+ root_dir; write("Working Directory: "+ root_dir +"\n"); f_ptr = 1; current_file_length = 0; current_file = 0; buffer = 0; in_use = 1; buffer_eof = 0; fill_buffer(); call_out("tar_extract",1); return 1; }