00001 /*
00002 File: FileName.cc
00003
00004 Function: Implements FileName.h
00005
00006 Author: Andrew Willmott
00007
00008 Notes:
00009 */
00010
00011 #include "cl/FileName.h"
00012 #include "cl/CLConfig.h"
00013 #include <stdio.h>
00014 #include <sys/stat.h>
00015 #include <stdlib.h>
00016 #include <unistd.h>
00017
00018 Void FileName::RemoveExtension()
00019 {
00020 Int dotPos;
00021
00022 dotPos = name.FindCharLast('.');
00023
00024 if (dotPos >= 0)
00025 {
00026 extension = name.Suffix(-1 - dotPos);
00027 name = name.Prefix(dotPos);
00028 }
00029 else
00030 extension = "";
00031 }
00032
00033 Void FileName::AddExtension(StrConst ext)
00034 {
00035 name = name + "." + extension;
00036 extension = ext;
00037 }
00038
00039 String FileName::GetPath() const
00040 {
00041 String result;
00042
00043 #ifdef CL_MACOS
00044 result.Printf("%s.%s", name.CString(), extension.CString());
00045 #else
00046 if (extension == "")
00047 result.Printf("%s/%s", path.CString(), name.CString());
00048 else
00049 result.Printf("%s/%s.%s", path.CString(), name.CString(), extension.CString());
00050 #endif
00051
00052 return(result);
00053 }
00054
00055 FileName &FileName::SetPath(StrConst filePath)
00056 {
00057 Int slashPos;
00058 TempString thePath = SubstituteEnvVars(filePath);
00059
00060 slashPos = thePath.FindCharLast('/');
00061
00062 if (slashPos >= 0)
00063 {
00064 path = thePath.Prefix(slashPos);
00065 name = thePath.Suffix(-1 - slashPos);
00066 }
00067 else
00068 {
00069 path = ".";
00070 name = thePath;
00071 }
00072
00073 RemoveExtension();
00074
00075 return(SELF);
00076 }
00077
00078 FileName &FileName::SetRelPath(StrConst filePath)
00079 {
00080 Int slashPos;
00081 TempString thePath = SubstituteEnvVars(filePath);
00082
00083 if (thePath[0] == '/')
00084 // absolute path
00085 return(SetPath(filePath));
00086
00087 slashPos = thePath.FindCharLast('/');
00088
00089 if (slashPos >= 0)
00090 {
00091 path = path + "/" + thePath.Prefix(slashPos);
00092 name = thePath.Suffix(-(slashPos + 1));
00093 }
00094 else
00095 name = thePath;
00096
00097 RemoveExtension();
00098
00099 return(SELF);
00100 }
00101
00102 Bool FileName::Exists() const
00103 {
00104 return(access(GetPath().CString(), F_OK) == 0);
00105 }
00106
00107 Bool FileName::IsReadable() const
00108 {
00109 return(access(GetPath().CString(), R_OK) == 0);
00110 }
00111
00112 Bool FileName::IsWritable() const
00113 {
00114 return(access(GetPath().CString(), W_OK) == 0);
00115 }
00116
00117 Long FileName::GetTimeStamp() const
00118 {
00119 struct stat statInfo;
00120
00121 stat(GetPath().CString(), &statInfo);
00122
00123 return(statInfo.st_mtime);
00124 }
00125
00126 String TempPath()
00127 {
00128 String result = SubstituteEnvVars("$TMPDIR");
00129
00130 if (result[0] == '<')
00131 result = "/tmp";
00132
00133 return(result);
00134 }
00135
00136 StrConst tCompressExtensions[] =
00137 {
00138 "gz",
00139 "bz2",
00140 "Z",
00141 0
00142 };
00143
00144
00145 Int FileName::FindFileExtension(StrConst extensions[], Bool allowCompressed)
00162 {
00163 Int i, j;
00164 Bool extWasSet;
00165
00166 flags.Clear();
00167
00168 extWasSet = (extension != "");
00169
00170 if (extWasSet)
00171 // an extension is already set -- at most we might have to
00172 // tack on a compression suffix.
00173 {
00174 // remove any compression suffix
00175 if (allowCompressed)
00176 for (j = 0; !tCompressExtensions[j].IsNull(); j++)
00177 if (extension == tCompressExtensions[j])
00178 {
00179 if (IsReadable())
00180 flags.Set(1 << j);
00181 RemoveExtension();
00182 break;
00183 }
00184
00185 // check that the extension is valid
00186 for (i = 0; !extensions[i].IsNull(); i++)
00187 if (extension == extensions[i])
00188 break;
00189
00190 if (extensions[i].IsNull())
00191 return(kBadExtension);
00192
00193 if (flags.IsSet(FN_IsCompressed) || IsReadable())
00194 return(i);
00195 else
00196 {
00197 if (allowCompressed)
00198 // try it with a compression extension
00199 {
00200 AddExtension("");
00201
00202 for (j = 0; !tCompressExtensions[j].IsNull(); j++)
00203 {
00204 SetExtension(tCompressExtensions[j]);
00205
00206 if (IsReadable())
00207 {
00208 RemoveExtension();
00209 flags.Set(1 << j);
00210
00211 return(i);
00212 }
00213 }
00214
00215 RemoveExtension();
00216 }
00217
00218 return(kFileNotFound);
00219 }
00220 }
00221
00222 // try all possible extensions and compressions
00223 for (i = 0; !extensions[i].IsNull(); i++)
00224 {
00225 SetExtension(extensions[i]);
00226
00227 if (IsReadable())
00228 return(i);
00229
00230 // try it with a compression extension
00231 if (allowCompressed)
00232 {
00233 AddExtension("");
00234
00235 for (j = 0; !tCompressExtensions[j].IsNull(); j++)
00236 {
00237 SetExtension(tCompressExtensions[j]);
00238
00239 if (IsReadable())
00240 {
00241 RemoveExtension();
00242 flags.Set(1 << j);
00243
00244 return(i);
00245 }
00246 }
00247
00248 RemoveExtension();
00249 }
00250 }
00251
00252 SetExtension("");
00253
00254 return(kFileNotFound);
00255 }
00256
00257 FileName &FileName::MakeUnique()
00258 {
00259 if (Exists())
00260 {
00261 String origName = name;
00262 Int i = 0;
00263
00264 do
00265 {
00266 i++;
00267 name.Printf("%s-%d", origName.CString(), i);
00268 }
00269 while (Exists());
00270 }
00271
00272 return(SELF);
00273 }
00274
00275 Void FileName::AddCompExt()
00276 {
00277 if (flags.IsSet(FN_Gzipped))
00278 AddExtension("gz");
00279 else if (flags.IsSet(FN_Bz2ed))
00280 AddExtension("bz2");
00281 else if (flags.IsSet(FN_Compress))
00282 AddExtension("Z");
00283 }
00284
00285 Int FileName::DecompressSetup()
00286 {
00287 if (flags.IsSet(FN_IsCompressed))
00288 {
00289 String origFile;
00290 StrConst cmd;
00291 Int err;
00292
00293 AddCompExt();
00294 origFile = GetPath();
00295 RemoveExtension();
00296 SetDir(TempPath());
00297
00298 if (flags.IsSet(FN_Gzipped))
00299 cmd = "gunzip -c";
00300 else if (flags.IsSet(FN_Bz2ed))
00301 cmd = "bunzip2 -c";
00302 else if (flags.IsSet(FN_Compress))
00303 cmd = "compress -c";
00304
00305 if (system(cmd + " " + origFile + " > " + GetPath()) != 0)
00306 return(-1);
00307 }
00308
00309 return(0);
00310 }
00311
00312 Void FileName::DecompressCleanup()
00313 {
00314 if (flags.IsSet(FN_IsCompressed))
00315 unlink(GetPath());
00316 }