00001
00002
00003
00004 #ifndef _GTAR_FILE_H_
00005 #define _GTAR_FILE_H_
00006
00007 #include "ZlibWrapper.h"
00008
00010 class GTarParser
00011 {
00012 public:
00017 struct GTarFile
00018 {
00019 GVariant Dir;
00020 GVariant Name;
00021 GDateTime Modified;
00022 int64 Size;
00023
00024 int Blocks()
00025 {
00026 return (Size / 512) + (Size % 512 ? 1 : 0);
00027 }
00028 };
00029
00031 struct GTarHdr
00032 {
00033 char Name[100];
00034 char Mode[8];
00035 char Owner[8];
00036 char Group[8];
00037 char Size[12];
00038 char ModifiedTime[12];
00039 char CheckSum[8];
00040 char Type;
00041 char LinkedFile[100];
00042
00043 char Ustar[6];
00044 char Ver[2];
00045 char OwnerUserName[32];
00046 char OwnerGrpName[32];
00047 char DeviceMaj[8];
00048 char DeviceMin[8];
00049 char FilePrefix[155];
00050
00051 char Reserved[12];
00052 };
00053
00054 protected:
00056 Zlib z;
00057
00059 GZlibFile f;
00060
00062 int64 Octal(char *o)
00063 {
00064 int64 i = 0;
00065
00066 while (*o)
00067 {
00068 if (*o < '0' || *o > '7')
00069 break;
00070
00071 int s = *o - '0';
00072 i <<= 3;
00073 i |= s;
00074 o++;
00075 }
00076
00077 return i;
00078 }
00079
00081 GArray<GTarFile> *Files;
00082
00084 char *ExtractTo;
00085
00088 virtual bool Process(GTarFile &f, GStream &s, bool &SkipFile)
00089 {
00090 if (Files)
00091 {
00092 Files->New() = f;
00093 }
00094 if (ExtractTo)
00095 {
00096 char o[MAX_PATH];
00097 LgiMakePath(o, sizeof(o), ExtractTo, f.Dir.Str());
00098 if (!DirExists(o))
00099 FileDev->CreateDirectory(o);
00100 LgiMakePath(o, sizeof(o), o, f.Name.Str());
00101 GFile Out;
00102 if (Out.Open(o, O_WRITE))
00103 {
00104 char Buf[512];
00105 int Blocks = f.Blocks();
00106 int64 ToWrite = f.Size;
00107 for (int i=0; i<Blocks; i++)
00108 {
00109 int r = s.Read(Buf, sizeof(Buf));
00110 if (r <= 0)
00111 return false;
00112
00113 int Len = ToWrite < r ? ToWrite : r;
00114 int w = Out.Write(Buf, Len);
00115 if (w != Len)
00116 return false;
00117
00118 ToWrite -= w;
00119 }
00120
00121 SkipFile = true;
00122 }
00123 }
00124
00125 return true;
00126 }
00127
00129 bool Parse(char *FileName, int Mode)
00130 {
00131 bool Status = false;
00132
00133 if (Status = f.Open(FileName, Mode))
00134 {
00135 GTarHdr Hdr;
00136 int Size = sizeof(Hdr);
00137
00138 int r;
00139 while ((r = f.Read(&Hdr, sizeof(Hdr))) > 0)
00140 {
00141 int64 FileSize = Octal(Hdr.Size);
00142 if (FileSize)
00143 {
00144 GTarFile t;
00145 char *d = strrchr(Hdr.Name, '/');
00146 if (d == Hdr.Name)
00147 t.Name = Hdr.Name + 1;
00148 else if (d)
00149 {
00150 *d++ = 0;
00151 t.Name = d;
00152 t.Dir = Hdr.Name;
00153 d[-1] = '/';
00154 }
00155 else
00156 t.Name = Hdr.Name;
00157
00158 t.Size = FileSize;
00159
00160 int ModTime = Octal(Hdr.ModifiedTime);
00161 t.Modified.Set((time_t)ModTime);
00162
00163 bool SkipFile = true;
00164 if (!Process(t, f, SkipFile))
00165 break;
00166
00167 if (SkipFile)
00168 {
00169
00170 int Blocks = t.Blocks();
00171 char Buf[512];
00172 for (int i=0; i<Blocks; i++)
00173 {
00174 r = f.Read(&Buf, sizeof(Buf));
00175 if (r != sizeof(Buf))
00176 {
00177 break;
00178 }
00179 }
00180 }
00181 }
00182 }
00183 }
00184
00185 return Status;
00186 }
00187
00188 public:
00189 GTarParser() : f(&z)
00190 {
00191 Files = 0;
00192 ExtractTo = 0;
00193 }
00194
00196 bool DirList(char *File, GArray<GTarFile> &Out)
00197 {
00198 bool Status = false;
00199
00200 Files = &Out;
00201 Status = Parse(File, O_READ);
00202 Files = 0;
00203
00204 return Status;
00205 }
00206
00208 bool Extract(char *File, char *OutFolder)
00209 {
00210 bool Status = false;
00211
00212 if (OutFolder)
00213 {
00214 ExtractTo = OutFolder;
00215 Status = Parse(File, O_READ);
00216 ExtractTo = 0;
00217 }
00218
00219 return Status;
00220 }
00221 };
00222
00223 #endif