123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- program MiniUnz;
- { mini unzip demo package by Gilles Vollant
- Usage : miniunz [-exvlo] file.zip [file_to_extract]
- -l or -v list the content of the zipfile.
- -e extract a specific file or all files if [file_to_extract] is missing
- -x like -e, but extract without path information
- -o overwrite an existing file without warning
- Pascal translation
- Copyright (C) 2000 by Jacques Nomssi Nzali
- For conditions of distribution and use, see copyright notice in readme.txt
- }{$ifdef WIN32}
- {$define Delphi}
- {$ifndef FPC}
- {$define Delphi32}
- {$endif}
- {$endif}
- uses
- sysutils,
- {$ifdef Delphi}
- Windows,
- {$else}
- zlib,
- {$endif}
- ziputils,
- paszlib,
- ctypes,
- unzip;
- const
- CASESENSITIVITY = 0;
- WRITEBUFFERSIZE = 8192;
- { change_file_date : change the date/time of a file
- filename : the filename of the file where date/time must be modified
- dosdate : the new date at the MSDos format (4 bytes)
- tmu_date : the SAME new date at the tm_unz format }
- procedure change_file_date(const filename: PChar; dosdate: longword; tmu_date: tm_unz);
- {$ifdef Delphi32}
- var
- hFile: THandle;
- ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite: TFileTime;
- begin
- hFile := CreateFile(filename, GENERIC_READ or GENERIC_WRITE,
- 0, nil, OPEN_EXISTING, 0, 0);
- GetFileTime(hFile, @ftCreate, @ftLastAcc, @ftLastWrite);
- DosDateTimeToFileTime(word((dosdate shl 16)), word(dosdate), ftLocal);
- LocalFileTimeToFileTime(ftLocal, ftm);
- SetFileTime(hFile, @ftm, @ftLastAcc, @ftm);
- CloseHandle(hFile);
- end;
- {$else}
- {$if defined(FPC) and defined(win32)}
- var
- hFile : THandle;
- ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite : TFileTime;
- begin
- hFile := CreateFile(filename,GENERIC_READ or GENERIC_WRITE,
- 0,NIL,OPEN_EXISTING,0,0);
- GetFileTime(hFile, @ftCreate, @ftLastAcc, @ftLastWrite);
- DosDateTimeToFileTime(WORD((dosdate shl 16)), WORD(dosdate), @ftLocal);
- LocalFileTimeToFileTime(ftLocal, ftm);
- SetFileTime(hFile,ftm, ftLastAcc, ftm);
- CloseHandle(hFile);
- end;
- {$else} { msdos }
- begin
- FileSetDate(filename,dosdate);
- end;
- {$endif}
- {$endif}
- { mymkdir and change_file_date are not 100 % portable
- As I don't know well Unix, I wait feedback for the unix portion }
- function mymkdir(dirname: PChar): boolean;
- var
- S: string;
- begin
- S := StrPas(dirname);
- {$I-}
- mkdir(S);
- mymkdir := IOresult = 0;
- end;
- function makedir(newdir: PChar): boolean;
- var
- buffer: PChar;
- p: PChar;
- len: cint;
- var
- hold: char;
- begin
- makedir := False;
- len := strlen(newdir);
- if (len <= 0) then
- exit;
- buffer := PChar(allocmem( len + 1));
- strcopy(buffer, newdir);
- if (buffer[len - 1] = '/') then
- buffer[len - 1] := #0;
- if mymkdir(buffer) then
- begin
- if Assigned(buffer) then
- freemem( buffer);
- makedir := True;
- exit;
- end;
- p := buffer + 1;
- while True do
- begin
- while ((p^ <> #0) and (p^ <> '\') and (p^ <> '/')) do
- Inc(p);
- hold := p^;
- p^ := #0;
- if (not mymkdir(buffer)) {and (errno = ENOENT)} then
- begin
- WriteLn('couldn''t create directory ', buffer);
- if Assigned(buffer) then
- freemem( buffer);
- exit;
- end;
- if (hold = #0) then
- break;
- p^ := hold;
- Inc(p);
- end;
- if Assigned(buffer) then
- freemem( buffer);
- makedir := True;
- end;
- procedure do_banner;
- begin
- WriteLn('MiniUnz 0.15, demo package written by Gilles Vollant');
- WriteLn('Pascal port by Jacques Nomssi Nzali');
- WriteLn('more info at http://wwww.tu-chemnitz.de/~nomssi/paszlib.html');
- WriteLn;
- end;
- procedure do_help;
- begin
- WriteLn('Usage : miniunz [-exvlo] file.zip [file_to_extract]');
- WriteLn;
- end;
- function LeadingZero(w: word): string;
- var
- s: string;
- begin
- Str(w: 0, s);
- if Length(s) = 1 then
- s := '0' + s;
- LeadingZero := s;
- end;
- function HexToStr(w: clong): string;
- const
- ByteToChar: array[0..$F] of char = '0123456789ABCDEF';
- var
- s: string;
- i: cint;
- x: clong;
- begin
- s := '';
- x := w;
- for i := 0 to 3 do
- begin
- s := ByteToChar[byte(x) shr 4] + ByteToChar[byte(x) and $F] + s;
- x := x shr 8;
- end;
- HexToStr := s;
- end;
- function do_list(uf: unzFile): cint;
- var
- i: longword;
- gi: unz_global_info;
- err: cint;
- var
- filename_inzip: array[0..255] of char;
- file_info: unz_file_info;
- ratio: longword;
- string_method: string[255];
- var
- iLevel: cuInt;
- begin
- err := unzGetGlobalInfo(uf, gi);
- if (err <> UNZ_OK) then
- WriteLn('error ', err, ' with zipfile in unzGetGlobalInfo');
- WriteLn(' Length Method Size Ratio Date Time CRC-32 Name');
- WriteLn(' ------ ------ ---- ----- ---- ---- ------ ----');
- for i := 0 to gi.number_entry - 1 do
- begin
- ratio := 0;
- err := unzGetCurrentFileInfo(uf, @file_info, filename_inzip, sizeof(filename_inzip), nil, 0, nil, 0);
- if (err <> UNZ_OK) then
- begin
- WriteLn('error ', err, ' with zipfile in unzGetCurrentFileInfo');
- break;
- end;
- if (file_info.uncompressed_size > 0) then
- ratio := (file_info.compressed_size * 100) div file_info.uncompressed_size;
- if (file_info.compression_method = 0) then
- string_method := 'Stored'
- else
- if (file_info.compression_method = Z_DEFLATED) then
- begin
- iLevel := cuInt((file_info.flag and $06) div 2);
- case iLevel of
- 0: string_method := 'Defl:N';
- 1: string_method := 'Defl:X';
- 2, 3: string_method := 'Defl:F'; { 2:fast , 3 : extra fast}
- else
- string_method := 'Unkn. ';
- end;
- end;
- WriteLn(file_info.uncompressed_size: 7, ' ',
- string_method: 6, ' ',
- file_info.compressed_size: 7, ' ',
- ratio: 3, '% ', LeadingZero(longword(file_info.tmu_date.tm_mon) + 1), '-',
- LeadingZero(longword(file_info.tmu_date.tm_mday)): 2, '-',
- LeadingZero(longword(file_info.tmu_date.tm_year mod 100)): 2, ' ',
- LeadingZero(longword(file_info.tmu_date.tm_hour)), ':',
- LeadingZero(longword(file_info.tmu_date.tm_min)), ' ',
- HexToStr(longword(file_info.crc)), ' ',
- filename_inzip);
- if ((i + 1) < gi.number_entry) then
- begin
- err := unzGoToNextFile(uf);
- if (err <> UNZ_OK) then
- begin
- WriteLn('error ', err, ' with zipfile in unzGoToNextFile');
- break;
- end;
- end;
- end;
- do_list := 0;
- end;
- function do_extract_currentfile(uf: unzFile; const popt_extract_without_path: cint; var popt_overwrite: cint): cint;
- var
- filename_inzip: packed array[0..255] of char;
- filename_withoutpath: PChar;
- p: PChar;
- err: cint;
- fout: FILEptr;
- buf: pointer;
- size_buf: cuInt;
- file_info: unz_file_info;
- var
- write_filename: PChar;
- skip: cint;
- var
- rep: char;
- ftestexist: FILEptr;
- var
- answer: string[127];
- var
- c: char;
- begin
- fout := nil;
- err := unzGetCurrentFileInfo(uf, @file_info, filename_inzip,
- sizeof(filename_inzip), nil, 0, nil, 0);
- if (err <> UNZ_OK) then
- begin
- WriteLn('error ', err, ' with zipfile in unzGetCurrentFileInfo');
- do_extract_currentfile := err;
- exit;
- end;
- size_buf := WRITEBUFFERSIZE;
- buf := allocmem(size_buf);
- if (buf = nil) then
- begin
- WriteLn('Error allocating memory');
- do_extract_currentfile := UNZ_INTERNALERROR;
- exit;
- end;
- filename_withoutpath := filename_inzip;
- p := filename_withoutpath;
- while (p^ <> #0) do
- begin
- if (p^ = '/') or (p^ = '\') then
- filename_withoutpath := p + 1;
- Inc(p);
- end;
- if (filename_withoutpath^ = #0) then
- begin
- if (popt_extract_without_path = 0) then
- begin
- WriteLn('creating directory: ', filename_inzip);
- mymkdir(filename_inzip);
- end;
- end
- else
- begin
- skip := 0;
- if (popt_extract_without_path = 0) then
- write_filename := filename_inzip
- else
- write_filename := filename_withoutpath;
- err := unzOpenCurrentFile(uf);
- if (err <> UNZ_OK) then
- WriteLn('error ', err, ' with zipfile in unzOpenCurrentFile');
- if ((popt_overwrite = 0) and (err = UNZ_OK)) then
- begin
- rep := #0;
- ftestexist := fopen(write_filename, fopenread);
- if (ftestexist <> nil) then
- begin
- fclose(ftestexist);
- repeat
- Write('The file ', write_filename,
- ' exist. Overwrite ? [y]es, [n]o, [A]ll: ');
- ReadLn(answer);
- rep := answer[1];
- if ((rep >= 'a') and (rep <= 'z')) then
- Dec(rep, $20);
- until (rep = 'Y') or (rep = 'N') or (rep = 'A');
- end;
- if (rep = 'N') then
- skip := 1;
- if (rep = 'A') then
- popt_overwrite := 1;
- end;
- if (skip = 0) and (err = UNZ_OK) then
- begin
- fout := fopen(write_filename, fopenwrite);
- { some zipfile don't contain directory alone before file }
- if (fout = nil) and (popt_extract_without_path = 0) and
- (filename_withoutpath <> PChar(@filename_inzip)) then
- begin
- c := (filename_withoutpath - 1)^;
- (filename_withoutpath -1)^ := #0;
- makedir(write_filename);
- (filename_withoutpath -1)^ := c;
- fout := fopen(write_filename, fopenwrite);
- end;
- if (fout = nil) then
- WriteLn('error opening ', write_filename);
- end;
- if (fout <> nil) then
- begin
- WriteLn(' extracting: ', write_filename);
- repeat
- err := unzReadCurrentFile(uf, buf, size_buf);
- if (err < 0) then
- begin
- WriteLn('error ', err, ' with zipfile in unzReadCurrentFile');
- break;
- end;
- if (err > 0) then
- if (fwrite(buf, err, 1, fout) <> 1) then
- begin
- WriteLn('error in writing extracted file');
- err := UNZ_ERRNO;
- break;
- end;
- until (err = 0);
- fclose(fout);
- if (err = 0) then
- change_file_date(write_filename, file_info.dosDate,
- file_info.tmu_date);
- end;
- if (err = UNZ_OK) then
- begin
- err := unzCloseCurrentFile(uf);
- if (err <> UNZ_OK) then
- WriteLn('error ', err, ' with zipfile in unzCloseCurrentFile')
- else
- unzCloseCurrentFile(uf); { don't lose the error }
- end;
- end;
- if buf <> nil then
- freemem( buf);
- do_extract_currentfile := err;
- end;
- function do_extract(uf: unzFile; opt_extract_without_path: cint; opt_overwrite: cint): cint;
- var
- i: longword;
- gi: unz_global_info;
- err: cint;
- begin
- err := unzGetGlobalInfo(uf, gi);
- if (err <> UNZ_OK) then
- WriteLn('error ', err, ' with zipfile in unzGetGlobalInfo ');
- for i := 0 to gi.number_entry - 1 do
- begin
- if (do_extract_currentfile(uf, opt_extract_without_path,
- opt_overwrite) <> UNZ_OK) then
- break;
- if ((i + 1) < gi.number_entry) then
- begin
- err := unzGoToNextFile(uf);
- if (err <> UNZ_OK) then
- begin
- WriteLn('error ', err, ' with zipfile in unzGoToNextFile');
- break;
- end;
- end;
- end;
- do_extract := 0;
- end;
- function do_extract_onefile(uf: unzFile; const filename: PChar; opt_extract_without_path: cint; opt_overwrite: cint): cint;
- begin
- if (unzLocateFile(uf, filename, CASESENSITIVITY) <> UNZ_OK) then
- begin
- WriteLn('file ', filename, ' not found in the zipfile');
- do_extract_onefile := 2;
- exit;
- end;
- if (do_extract_currentfile(uf, opt_extract_without_path,
- opt_overwrite) = UNZ_OK) then
- do_extract_onefile := 0
- else
- do_extract_onefile := 1;
- end;
- { -------------------------------------------------------------------- }
- function main: cint;
- const
- zipfilename: PChar = nil;
- filename_to_extract: PChar = nil;
- var
- i: cint;
- opt_do_list: cint;
- opt_do_extract: cint;
- opt_do_extract_withoutpath: cint;
- opt_overwrite: cint;
- filename_try: array[0..512 - 1] of char;
- uf: unzFile;
- var
- p: cint;
- pstr: string[255];
- c: char;
- begin
- opt_do_list := 0;
- opt_do_extract := 1;
- opt_do_extract_withoutpath := 0;
- opt_overwrite := 0;
- uf := nil;
- do_banner;
- if (ParamCount = 0) then
- begin
- do_help;
- Halt(0);
- end
- else
- for i := 1 to ParamCount do
- begin
- pstr := ParamStr(i);
- if pstr[1] = '-' then
- for p := 2 to Length(pstr) do
- begin
- c := pstr[p];
- case UpCase(c) of
- 'L',
- 'V': opt_do_list := 1;
- 'X': opt_do_extract := 1;
- 'E':
- begin
- opt_do_extract := 1;
- opt_do_extract_withoutpath := 1;
- end;
- 'O': opt_overwrite := 1;
- end;
- end
- else
- begin
- pstr := pstr + #0;
- if (zipfilename = nil) then
- zipfilename := StrNew(PChar(@pstr[1]))
- else
- if (filename_to_extract = nil) then
- filename_to_extract := StrNew(PChar(@pstr[1]));
- end;
- end{ for };
- if (zipfilename <> nil) then
- begin
- strcopy(filename_try, zipfilename);
- uf := unzOpen(zipfilename);
- if (uf = nil) then
- begin
- strcat(filename_try, '.zip');
- uf := unzOpen(filename_try);
- end;
- end;
- if (uf = nil) then
- begin
- WriteLn('Cannot open ', zipfilename, ' or ', zipfilename, '.zip');
- Halt(1);
- end;
- WriteLn(filename_try, ' opened');
- if (opt_do_list = 1) then
- begin
- main := do_list(uf);
- exit;
- end
- else
- if (opt_do_extract = 1) then
- if (filename_to_extract = nil) then
- begin
- main := do_extract(uf, opt_do_extract_withoutpath, opt_overwrite);
- exit;
- end
- else
- begin
- main := do_extract_onefile(uf, filename_to_extract,
- opt_do_extract_withoutpath, opt_overwrite);
- exit;
- end;
- unzCloseCurrentFile(uf);
- strDispose(zipfilename);
- strDispose(filename_to_extract);
- main := 0;
- end;
- begin
- main;
- Write('Done...');
- Readln;
- end.
|