bool IsFullDirectory(const String& d) { if(IsFullPath(d)) { FindFile ff(d); if(ff) return ff.IsDirectory(); } return false; }
String GetExeFilePath() { static String exepath; ONCELOCK { const char *exe = procexepath_(); if(*exe) exepath = exe; else { String x = Argv0__; if(IsFullPath(x) && FileExists(x)) exepath = x; else { exepath = GetHomeDirFile("upp"); Vector<String> p = Split(FromSystemCharset(Environment().Get("PATH")), ':'); if(x.Find('/') >= 0) p.Add(GetCurrentDirectory()); for(int i = 0; i < p.GetCount(); i++) { String ep = NormalizePath(AppendFileName(p[i], x)); if(FileExists(ep)) exepath = ep; } } } } return exepath; }
// We should return 'true' even if resulting path is shorter than MAX_PATH, // because we can also use this function to open files with non-standard // characters, even if their path length is normal. bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize) { const wchar *Prefix=L"\\\\?\\"; const size_t PrefixLength=4; bool FullPath=IsDiskLetter(Src) && IsPathDiv(Src[2]); size_t SrcLength=wcslen(Src); if (IsFullPath(Src)) // Paths in d:\path\name format. { if (IsDiskLetter(Src)) { if (MaxSize<=PrefixLength+SrcLength) return false; wcsncpy(Dest,Prefix,PrefixLength); wcscpy(Dest+PrefixLength,Src); return true; } else if (Src[0]=='\\' && Src[1]=='\\') { if (MaxSize<=PrefixLength+SrcLength+2) return false; wcsncpy(Dest,Prefix,PrefixLength); wcscpy(Dest+PrefixLength,L"UNC"); wcscpy(Dest+PrefixLength+3,Src+1); return true; } // We may be here only if we modify IsFullPath in the future. return false; } else { wchar CurDir[NM]; DWORD DirCode=GetCurrentDirectory(ASIZE(CurDir)-1,CurDir); if (DirCode==0 || DirCode>ASIZE(CurDir)-1) return false; if (IsPathDiv(Src[0])) // Paths in \path\name format. { if (MaxSize<=PrefixLength+SrcLength+2) return false; wcsncpy(Dest,Prefix,PrefixLength); wcsncpy(Dest+PrefixLength,CurDir,2); // Copy drive letter 'd:'. wcscpy(Dest+PrefixLength+2,Src); return true; } else // Paths in path\name format. { AddEndSlash(CurDir,ASIZE(CurDir)); if (MaxSize<=PrefixLength+wcslen(CurDir)+SrcLength) return false; wcsncpy(Dest,Prefix,PrefixLength); wcscpy(Dest+PrefixLength,CurDir); wcsncatz(Dest,Src,MaxSize); return true; } } return false; }
bool FileSelector::Execute(bool open, const char *title) { Ctrl::ReleaseCtrlCapture(); if(!title) title = open ? t_("Open") : t_("Save as"); Ctrl *w = Ctrl::GetActiveWindow(); GtkWidget *fc = gtk_file_chooser_dialog_new(title, w ? w->gtk() : NULL, open ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, open ? GTK_STOCK_OPEN : GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc), confirm); gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(fc), true); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(fc), multi); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(fc), hidden); if(IsFullPath(ipath)) { FindFile ff(ipath); if(ff) if(ff.IsFolder()) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc), ipath); else gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fc), ipath); else { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc), GetFileFolder(ipath)); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), GetFileName(ipath)); } } else gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), ipath); ipath.Clear(); for(int i = 0; i < type.GetCount(); i++) { GtkFileFilter *filter = gtk_file_filter_new(); gtk_file_filter_set_name(filter, type[i].a); gtk_file_filter_add_pattern(filter, type[i].b); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc), filter); if(i == activetype) gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fc), filter); } bool ret = false; path.Clear(); if(gtk_dialog_run(GTK_DIALOG(fc)) == GTK_RESPONSE_OK) { GSList *list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(fc)); if(list) { GSList *l; for(l = list; l; l = l->next) { path.Add((const char *)l->data); g_free(l->data); } g_slist_free (list); } ret = true; } gtk_widget_destroy(fc); return ret; }
LPSTR ReadFilePush(LPSTR pszfile) { FILE *pf; assert(Frb.fOpen); OpenFilePush(IsFullPath(pszfile) ? "" : Frb.pszFile, pszfile, Frb.pszCommentToEOL, &pf); return(ReadLine(Frb.pf)); }
String Nest::PackagePath0(const String& name) { String uppfile = NativePath(name); if(IsFullPath(uppfile)) return NormalizePath(uppfile); Vector<String> d = GetUppDirs(); String p; for(int i = 0; i < d.GetCount(); i++) { p = NormalizePath(AppendFileName(AppendFileName(d[i], uppfile), GetFileName(uppfile)) + ".upp"); if(FileExists(p)) return p; } return d.GetCount() ? NormalizePath(AppendFileName(AppendFileName(d[0], uppfile), GetFileName(uppfile)) + ".upp") : ""; }
String NormalizePath(const char *path, const char *currdir) { String join_path; if(!IsFullPath(path)) path = join_path = AppendFileName(currdir, path); String out; if(*path && path[1] == ':') { out << path[0] << ":\\"; path += 3; } else if(path[0] == '\\' && path[1] == '\\') { out = "\\\\"; path += 2; } else if(sDirSep(*path)) { if(*currdir) out << *currdir << ':'; out.Cat(DIR_SEP); path++; } int outstart = out.GetLength(); while(*path) { if(sDirSep(*path)) { while(sDirSep(*path)) path++; if(*path == '\0') break; if(out.IsEmpty() || *out.Last() != DIR_SEP) out.Cat(DIR_SEP); } const char *b = path; while(*path && !sDirSep(*path)) path++; if(path - b == 1 && *b == '.') ; //no-op else if(path - b == 2 && *b == '.' && b[1] == '.') { const char *ob = ~out + outstart, *oe = out.End(); if(oe - 1 > ob && oe[-1] == DIR_SEP) oe--; while(oe > ob && oe[-1] != DIR_SEP) oe--; out.Trim((int)(oe - out.Begin())); } else out.Cat(b, (int)(path - b)); } return out; }
String GetFileOnPath(const char* file, const char* paths, bool current, const char *curdir) { String ufn = NativePath(file); if(IsFullPath(ufn)) return ufn; String fn; #ifdef PLATFORM_WINCE if(current && curdir && FileExists(fn = NormalizePath(ufn, curdir))) ; #else String cd = curdir; if(!curdir) cd = GetCurrentDirectory(); if(current && FileExists(fn = NormalizePath(ufn, cd))) ; #endif else if(paths) { fn = Null; while(*paths) { const char* start = paths; #ifdef PLATFORM_WIN32 while(*paths && *paths != ';') paths++; #else while(*paths && *paths != ';' && *paths != ':') paths++; #endif String dir(start, (int)(paths - start)); if(!dir.IsEmpty()) { #ifdef PLATFORM_WINCE dir = NormalizePath(AppendFileName(NativePath(dir), ufn)); #else dir = NormalizePath(AppendFileName(NativePath(dir), ufn), cd); #endif if(FileExists(dir)) { fn = dir; break; } } if(*paths) paths++; } } return fn; }
bool CommandData::ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath) { char *Name=ConvertPath(CheckName,NULL); char FullName[NM],*CurName; *FullName=0; Args->Rewind(); while ((CurName=Args->GetString())!=NULL) #ifndef SFX_MODULE if (CheckFullPath && IsFullPath(CurName)) { if (*FullName==0) ConvertNameToFull(CheckName,FullName); if (CmpName(CurName,FullName,MATCH_WILDSUBPATH)) return(true); } else #endif if (CmpName(ConvertPath(CurName,NULL),Name,MATCH_WILDSUBPATH)) return(true); return(false); }
// Check the path length and display the error message if it is too long. void ErrorHandler::CheckLongPathErrMsg(const char *FileName,const wchar *FileNameW) { #if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined (SILENT) && defined(MAX_PATH) if (GetLastError()==ERROR_PATH_NOT_FOUND) { wchar WideFileName[NM]; GetWideName(FileName,FileNameW,WideFileName,ASIZE(WideFileName)); size_t NameLength=wcslen(WideFileName); if (!IsFullPath(WideFileName)) { wchar CurDir[NM]; GetCurrentDirectoryW(ASIZE(CurDir),CurDir); NameLength+=wcslen(CurDir)+1; } if (NameLength>MAX_PATH) { Log(NULL,St(MMaxPathLimit),MAX_PATH); } } #endif }
FILE * efopen(char *env) { char *t, *p; int port, sock; FILE *f = 0; unless (t = getenv(env)) return (0); if (IsFullPath(t)) { f = fopen(t, "a"); } else if ((p = strchr(t, ':')) && ((port = atoi(p+1)) > 0)) { *p = 0; sock = tcp_connect(t, port); *p = ':'; if (sock >= 0) f = fdopen(sock, "w"); } else { unless (f = fopen(DEV_TTY, "w")) f = fdopen(2, "w"); } if (f) setvbuf(f, 0, _IONBF, 0); return (f); }
void ConvertNameToFull(const wchar *Src,wchar *Dest,size_t MaxSize) { if (Src==NULL || *Src==0) { if (MaxSize>0) *Dest=0; return; } #ifdef _WIN_ALL { wchar FullName[NM],*NamePtr; DWORD Code=GetFullPathName(Src,ASIZE(FullName),FullName,&NamePtr); if (Code==0 || Code>ASIZE(FullName)) { wchar LongName[NM]; if (GetWinLongPath(Src,LongName,ASIZE(LongName))) Code=GetFullPathName(LongName,ASIZE(FullName),FullName,&NamePtr); } if (Code!=0 && Code<ASIZE(FullName)) wcsncpyz(Dest,FullName,MaxSize); else if (Src!=Dest) wcsncpyz(Dest,Src,MaxSize); } #elif defined(_UNIX) if (IsFullPath(Src)) *Dest=0; else { char CurDirA[NM]; if (getcwd(CurDirA,ASIZE(CurDirA))==NULL) *CurDirA=0; CharToWide(CurDirA,Dest,MaxSize); AddEndSlash(Dest,MaxSize); } wcsncatz(Dest,Src,MaxSize); #else wcsncpyz(Dest,Src,MaxSize); #endif }
void ErrorHandler::CreateErrorMsg(const char *ArcName,const char *FileName) { #ifndef SILENT Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotCreate),FileName); Alarm(); #if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && defined(MAX_PATH) if (GetLastError()==ERROR_PATH_NOT_FOUND) { size_t NameLength=strlen(FileName); if (!IsFullPath(FileName)) { char CurDir[NM]; GetCurrentDirectory(sizeof(CurDir),CurDir); NameLength+=strlen(CurDir)+1; } if (NameLength>MAX_PATH) { Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAX_PATH); } } #endif SysErrMsg(); #endif }
bool CommandData::ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode) { char *Name=ConvertPath(CheckName,NULL); char FullName[NM]; char CurMask[NM+1]; // We reserve the space to append "*" to mask. *FullName=0; Args->Rewind(); while (Args->GetString(CurMask,ASIZE(CurMask)-1)) { char *LastMaskChar=PointToLastChar(CurMask); bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only. if (Dir) { // CheckName is a directory. if (DirMask) { // We process the directory and have the directory exclusion mask. // So let's convert "mask\" to "mask" and process it normally. *LastMaskChar=0; } else { // If mask has wildcards in name part and does not have the trailing // '\' character, we cannot use it for directories. if (IsWildcard(PointToName(CurMask))) continue; } } else { // If we process a file inside of directory excluded by "dirmask\". // we want to exclude such file too. So we convert "dirmask\" to // "dirmask\*". It is important for operations other than archiving. // When archiving, directory matched by "dirmask\" is excluded // from further scanning. if (DirMask) strcat(CurMask,"*"); } #ifndef SFX_MODULE if (CheckFullPath && IsFullPath(CurMask)) { // We do not need to do the special "*\" processing here, because // onlike the "else" part of this "if", now we convert names to full // format, so they all include the path, which is matched by "*\" // correctly. Moreover, removing "*\" from mask would break // the comparison, because now all names have the path. if (*FullName==0) ConvertNameToFull(CheckName,FullName); if (CmpName(CurMask,FullName,MatchMode)) return(true); } else #endif { char NewName[NM+2],*CurName=Name; if (CurMask[0]=='*' && IsPathDiv(CurMask[1])) { // We want "*\name" to match 'name' not only in subdirectories, // but also in the current directory. We convert the name // from 'name' to '.\name' to be matched by "*\" part even if it is // in current directory. NewName[0]='.'; NewName[1]=CPATHDIVIDER; strncpyz(NewName+2,Name,ASIZE(NewName)-2); CurName=NewName; } if (CmpName(ConvertPath(CurMask,NULL),CurName,MatchMode)) return(true); } } return(false); }
bool IsTopicGroup(const char *path) { return ToLower(GetFileExt(path)) == ".tpp" && (!IsFullPath(path) || !FileExists(path)); }
BOOL SetupReadFile( LPSTR pszdir, LPSTR pszfile, LPSTR pszCommentToEOL, FILE **ppf ) { char path[DB_MAX_PATH_LENGTH]; assert(!Frb.fOpen); assert(Frb.pf == NULL); assert(Frb.pszFile == NULL); Frb.fMakefile = strcmp(pszCommentToEOL, "#") == 0; Frb.DateTime.value = 0; strcpy(path, pszdir); if (Frb.pfrbNext != NULL) { // if a nested open LPSTR p; if (Frb.fMakefile && !IsFullPath(pszfile)) { // nmake handles relative includes in makefiles by // attempting to locate the file relative to each makefile // in the complete include chain. FILEREADBUF *pfrb; for (pfrb = Frb.pfrbNext; pfrb != NULL; pfrb = pfrb->pfrbNext) { assert(pfrb->pszFile != NULL); strcpy(path, pfrb->pszFile); p = FindLastPathSeparator(path); if (p != NULL) { *p = '\0'; } if (ProbeFile(path, pszfile) != -1) { break; } } if (pfrb == NULL) { // Unable to find file anywhere along path. return FALSE; } } else { p = FindLastPathSeparator(path); if (p != NULL) { *p = '\0'; } } } if (!MyOpenFile(path, pszfile, "rb", ppf, TRUE)) { *ppf = NULL; return(FALSE); } if (Frb.fMakefile) { Frb.DateTime = (*pDateTimeFile)(path, pszfile); } Frb.cLine = 0; Frb.cNull = 0; Frb.cbTotal = 0; Frb.pf = *ppf; Frb.fEof = FALSE; Frb.pszCommentToEOL = pszCommentToEOL; Frb.cbCommentToEOL = strlen(pszCommentToEOL); if (fseek(Frb.pf, 0L, SEEK_END) != -1) { Frb.cbFile = ftell(Frb.pf); if (fseek(Frb.pf, 0L, SEEK_SET) == -1) { Frb.cbFile = 0; } } else { Frb.cbFile = 0; } Frb.cbBuffer = BigBufSize; if (Frb.pfrbNext != NULL) { if (Frb.cbBuffer > Frb.cbFile + 1) { Frb.cbBuffer = Frb.cbFile + 1; } AllocMem(Frb.cbBuffer, (VOID **) &Frb.pbBuffer, MT_IOBUFFER); } else { Frb.pbBuffer = BigBuf; } if (!ReadBuf(Frb.pf)) { fclose(Frb.pf); Frb.pf = *ppf = NULL; if (Frb.pfrbNext != NULL) { FreeMem((VOID **) &Frb.pbBuffer, MT_IOBUFFER); } return(FALSE); // zero byte file } if (path[0] != '\0') { strcat(path, PATH_SEPARATOR); } strcat(path, pszfile); MakeString(&Frb.pszFile, path, TRUE, MT_FRBSTRING); Frb.fOpen = TRUE; if (Frb.fMakefile && DEBUG_4) { BuildError( "Opening file: cbFile=%lu cbBuf=%lu\n", Frb.cbTotal, Frb.cbBuffer); } return(TRUE); }
bool IsFullRootPath(const wchar *Path) { return IsFullPath(Path) || IsPathDiv(Path[0]); }
String SourcePath(const String& package, const String& file) { if(IsFullPath(file)) return NativePath(file); return NormalizePath(AppendFileName(GetFileFolder(PackagePath(package)), file)); }
bool MakeBuild::BuildPackage(const Workspace& wspc, int pkindex, int pknumber, int pkcount, String mainparam, String outfile, Vector<String>& linkfile, String& linkopt, bool link) { String package = wspc[pkindex]; String mainpackage = wspc[0]; const Package& pkg = wspc.package[pkindex]; VectorMap<String, String> bm = GetMethodVars(method); if(bm.GetCount() == 0) { PutConsole("Invalid build method"); ConsoleShow(); return false; } One<Host> host = CreateHost(false); if(!IsNull(onefile)) { OneFileHost *h = new OneFileHost; h->host = host; h->onefile = onefile; host = h; } One<Builder> b = CreateBuilder(~host); if(!b) return false; b->config = PackageConfig(wspc, pkindex, bm, mainparam, *host, *b); const TargetMode& m = targetmode == 0 ? debug : release; b->version = m.version; b->method = method; b->outdir = OutDir(b->config, package, bm); host->RealizeDir(b->outdir); String mainfn = Null; Index<String> mcfg = PackageConfig(wspc, 0, bm, mainparam, *host, *b, &mainfn); HdependClearDependencies(); for(int i = 0; i < pkg.GetCount(); i++) { const Array<OptItem>& f = pkg[i].depends; for(int j = 0; j < f.GetCount(); j++) if(MatchWhen(f[j].when, mcfg.GetKeys())) HdependAddDependency(SourcePath(package, pkg[i]), SourcePath(package, f[j].text)); } String tout = OutDir(mcfg, mainpackage, bm, use_target); host->RealizeDir(tout); if(IsNull(mainfn)) mainfn = GetFileTitle(mainpackage) + b->GetTargetExt(); if(!IsNull(outfile)) target = NormalizePath(outfile, tout); else { if(m.target_override && !IsNull(m.target) && IsFolder(m.target)) target = host->NormalizePath(AppendFileName(m.target, mainfn)); else if(m.target_override && (IsFullPath(m.target) || *m.target == '/' || *m.target == '\\')) target = m.target; else if(m.target_override && !IsNull(m.target)) target = host->NormalizePath(AppendFileName(tout, m.target)); else if(IsFullPath(mainfn)) target = mainfn; else target = host->NormalizePath(AppendFileName(tout, mainfn)); } b->target = target; b->mainpackage = mainpackage; if(IsNull(onefile)) { String out; out << "----- " << package << " ( " << Join(b->config.GetKeys(), " ") << " )"; if(pkcount > 1) out << " (" << (pknumber + 1) << " / " << pkcount << ')'; PutConsole(out); } else b->config.FindAdd("NOLIB"); bool ok = b->BuildPackage(package, linkfile, linkopt, GetAllUses(wspc, pkindex), GetAllLibraries(wspc, pkindex, bm, mainparam, *host, *b), targetmode - 1); Vector<String> errors = PickErrors(); host->DeleteFile(errors); if(!ok || !errors.IsEmpty()) return false; if(link) { ok = b->Link(linkfile, linkopt, GetTargetMode().createmap); errors = PickErrors(); host->DeleteFile(errors); if(!ok || !errors.IsEmpty()) return false; } return true; }
static void LoadIniStream(Stream& in, VectorMap<String, String>& key, const char *sfile) { bool env = false; while(!in.IsEof()) { String line = in.GetLine(); CParser p(line); if(p.IsId()) { String k = p.ReadId(); if(p.Char('=')) { String h = TrimBoth((String)p.GetSpacePtr()); if(env) { String hh; const char *s = ~h; while(*s) { if(*s == '$') { s++; if(*s == '$') { hh.Cat('$'); s++; } else { String id; if (*s == '{') { while(*++s != '}') id.Cat(*s); s++; } else { while(iscid(*s)) id.Cat(*s++); } hh.Cat(GetEnv(id)); } } else hh.Cat(*s++); } key.Add(k, hh); } else key.Add(k, h); } } else if(p.Char('@')) { if(p.Id("include")) { String fn = p.GetPtr(); if(!IsFullPath(fn) && sfile) fn = AppendFileName(GetFileFolder(GetFullPath(sfile)), fn); LoadIniFile(fn, key); } else if(p.Id("end")) return; else if(p.Id("replace-env")) env = true; else if(p.Id("ignore-env")) env = false; } } }
bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) { static bool PrivSet=false; if (!PrivSet) { SetPrivilege(SE_RESTORE_NAME); // Not sure if we really need it, but let's request anyway. SetPrivilege(SE_CREATE_SYMBOLIC_LINK_NAME); PrivSet=true; } const DWORD BufSize=sizeof(REPARSE_DATA_BUFFER)+2*NM+1024; Array<byte> Buf(BufSize); REPARSE_DATA_BUFFER *rdb=(REPARSE_DATA_BUFFER *)&Buf[0]; wchar SubstName[NM]; wcsncpyz(SubstName,hd->RedirName,ASIZE(SubstName)); size_t SubstLength=unrar_wcslen(SubstName); wchar PrintName[NM],*PrintNameSrc=SubstName,*PrintNameDst=PrintName; bool WinPrefix=unrar_wcsncmp(PrintNameSrc,L"\\??\\",4)==0; if (WinPrefix) PrintNameSrc+=4; if (WinPrefix && unrar_wcsncmp(PrintNameSrc,L"UNC\\",4)==0) { *(PrintNameDst++)='\\'; // Insert second \ in beginning of share name. PrintNameSrc+=3; } unrar_wcscpy(PrintNameDst,PrintNameSrc); size_t PrintLength=unrar_wcslen(PrintName); bool AbsPath=WinPrefix; // IsFullPath is not really needed here, AbsPath check is enough. // We added it just for extra safety, in case some Windows version would // allow to create absolute targets with SYMLINK_FLAG_RELATIVE. if (!Cmd->AbsoluteLinks && (AbsPath || IsFullPath(hd->RedirName) || !IsRelativeSymlinkSafe(hd->FileName,hd->RedirName))) return false; #ifndef NOFILECREATE CreatePath(Name,true); // 'DirTarget' check is important for Unix symlinks to directories. // Unix symlinks do not have their own 'directory' attribute. if (hd->Dir || hd->DirTarget) { if (!CreateDirectory(Name,NULL)) return false; } else { HANDLE hFile=CreateFile(Name,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); if (hFile == INVALID_HANDLE_VALUE) return false; CloseHandle(hFile); } #endif if (hd->RedirType==FSREDIR_JUNCTION) { rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT; rdb->ReparseDataLength=USHORT( sizeof(rdb->MountPointReparseBuffer.SubstituteNameOffset)+ sizeof(rdb->MountPointReparseBuffer.SubstituteNameLength)+ sizeof(rdb->MountPointReparseBuffer.PrintNameOffset)+ sizeof(rdb->MountPointReparseBuffer.PrintNameLength)+ (SubstLength+1)*sizeof(WCHAR)+(PrintLength+1)*sizeof(WCHAR)); rdb->Reserved=0; rdb->MountPointReparseBuffer.SubstituteNameOffset=0; rdb->MountPointReparseBuffer.SubstituteNameLength=USHORT(SubstLength*sizeof(WCHAR)); unrar_wcscpy(rdb->MountPointReparseBuffer.PathBuffer,SubstName); rdb->MountPointReparseBuffer.PrintNameOffset=USHORT((SubstLength+1)*sizeof(WCHAR)); rdb->MountPointReparseBuffer.PrintNameLength=USHORT(PrintLength*sizeof(WCHAR)); unrar_wcscpy(rdb->MountPointReparseBuffer.PathBuffer+SubstLength+1,PrintName); } else if (hd->RedirType==FSREDIR_WINSYMLINK || hd->RedirType==FSREDIR_UNIXSYMLINK) { rdb->ReparseTag=IO_REPARSE_TAG_SYMLINK; rdb->ReparseDataLength=USHORT( sizeof(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset)+ sizeof(rdb->SymbolicLinkReparseBuffer.SubstituteNameLength)+ sizeof(rdb->SymbolicLinkReparseBuffer.PrintNameOffset)+ sizeof(rdb->SymbolicLinkReparseBuffer.PrintNameLength)+ sizeof(rdb->SymbolicLinkReparseBuffer.Flags)+ (SubstLength+1)*sizeof(WCHAR)+(PrintLength+1)*sizeof(WCHAR)); rdb->Reserved=0; rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset=0; rdb->SymbolicLinkReparseBuffer.SubstituteNameLength=USHORT(SubstLength*sizeof(WCHAR)); unrar_wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer,SubstName); rdb->SymbolicLinkReparseBuffer.PrintNameOffset=USHORT((SubstLength+1)*sizeof(WCHAR)); rdb->SymbolicLinkReparseBuffer.PrintNameLength=USHORT(PrintLength*sizeof(WCHAR)); unrar_wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer+SubstLength+1,PrintName); rdb->SymbolicLinkReparseBuffer.Flags=AbsPath ? 0:SYMLINK_FLAG_RELATIVE; } else return false; HANDLE hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,0,NULL, OPEN_EXISTING,FILE_FLAG_OPEN_REPARSE_POINT| FILE_FLAG_BACKUP_SEMANTICS,NULL); if (hFile==INVALID_HANDLE_VALUE) return false; DWORD Returned; if (!DeviceIoControl(hFile,FSCTL_SET_REPARSE_POINT,rdb, FIELD_OFFSET(REPARSE_DATA_BUFFER,GenericReparseBuffer)+ rdb->ReparseDataLength,NULL,0,&Returned,NULL)) { CloseHandle(hFile); uiMsg(UIERROR_SLINKCREATE,UINULL,Name); if (GetLastError()==ERROR_PRIVILEGE_NOT_HELD) uiMsg(UIERROR_NEEDADMIN); ErrHandler.SysErrMsg(); ErrHandler.SetErrorCode(RARX_CREATE); if (hd->Dir) RemoveDirectory(Name); else DeleteFile(Name); return false; } File LinkFile; LinkFile.SetHandle(hFile); LinkFile.SetOpenFileTime( Cmd->xmtime==EXTTIME_NONE ? NULL:&hd->mtime, Cmd->xctime==EXTTIME_NONE ? NULL:&hd->ctime, Cmd->xatime==EXTTIME_NONE ? NULL:&hd->atime); LinkFile.Close(); #ifndef NOFILECREATE if (!Cmd->IgnoreGeneralAttr) SetFileAttr(Name,hd->FileAttr); #endif return true; }
String VarFilePath() { String p = varsname; if(IsFullPath(varsname)) return varsname; return VarFilePath(GetVarsName()); }