* use new dir_reader
* only warn once about /a on POSIX * made /R search for matches inside subdirectories even wildcards were not used git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3782 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
7450c0f23b
commit
ee703bab52
2 changed files with 348 additions and 499 deletions
|
@ -13,6 +13,8 @@
|
|||
#include "exehead/fileform.h"
|
||||
#include "exehead/config.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
||||
// Added by Sunil Kamath 11 June 2003
|
||||
# include <time.h>
|
||||
|
@ -141,7 +143,13 @@ class CEXEBuild {
|
|||
#endif
|
||||
int doParse(const char *str);
|
||||
int doCommand(int which_token, LineParser &line);
|
||||
int do_add_file(const char *lgss, int attrib, int recurse, int linecnt, int *total_files, const char *name_override=0, int generatecode=1, int *data_handle=0, int rec_depth=0);
|
||||
|
||||
int do_add_file(const char *lgss, int attrib, int recurse, int *total_files, const char
|
||||
*name_override=0, int generatecode=1, int *data_handle=0, std::string& basedir=std::string(""));
|
||||
int add_file(const std::string& dir, const std::string& file, int attrib, const char
|
||||
*name_override, int generatecode, int *data_handle);
|
||||
int do_add_file_create_dir(const std::string& local_dir, const std::string& dir, int attrib=0);
|
||||
|
||||
GrowBuf m_linebuild; // used for concatenating lines
|
||||
|
||||
// used by doParse to do preprocessing
|
||||
|
|
|
@ -8,9 +8,12 @@
|
|||
#include "ResourceEditor.h"
|
||||
#include "DialogTemplate.h"
|
||||
#include "lang.h"
|
||||
#include "dirreader.h"
|
||||
#include "exehead/resource.h"
|
||||
#include <cassert> // for assert(3)
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <direct.h>
|
||||
#else
|
||||
|
@ -3982,7 +3985,11 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
}
|
||||
if (which_token == TOK_FILE && !stricmp(line.gettoken_str(a),"/a"))
|
||||
{
|
||||
#ifdef _WIN32
|
||||
attrib=1;
|
||||
#else
|
||||
warning_fl("%sFile /a is disabled for non Win32 platforms.",(which_token == TOK_FILE)?"":"Reserve");
|
||||
#endif
|
||||
a++;
|
||||
}
|
||||
if (!stricmp(line.gettoken_str(a),"/r"))
|
||||
|
@ -3998,10 +4005,10 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
|
||||
int tf=0;
|
||||
#ifdef _WIN32
|
||||
int v=do_add_file(line.gettoken_str(a), attrib, 0, linecnt,&tf,on);
|
||||
int v=do_add_file(line.gettoken_str(a), attrib, 0, &tf, on);
|
||||
#else
|
||||
char *fn = my_convert(line.gettoken_str(a));
|
||||
int v=do_add_file(fn, attrib, 0, linecnt,&tf,on);
|
||||
int v=do_add_file(fn, attrib, 0, &tf, on);
|
||||
my_convert_free(fn);
|
||||
#endif
|
||||
if (v != PS_OK) return v;
|
||||
|
@ -4040,10 +4047,10 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
}
|
||||
int tf=0;
|
||||
#ifdef _WIN32
|
||||
int v=do_add_file(t, attrib, rec, linecnt,&tf,NULL,which_token == TOK_FILE);
|
||||
int v=do_add_file(t, attrib, rec, &tf, NULL, which_token == TOK_FILE);
|
||||
#else
|
||||
char *fn = my_convert(t);
|
||||
int v=do_add_file(fn, attrib, rec, linecnt,&tf,NULL,which_token == TOK_FILE);
|
||||
int v=do_add_file(fn, attrib, rec, &tf, NULL, which_token == TOK_FILE);
|
||||
my_convert_free(fn);
|
||||
#endif
|
||||
if (v != PS_OK) return v;
|
||||
|
@ -5400,7 +5407,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
build_overwrite=1; // off
|
||||
int old_build_datesave=build_datesave;
|
||||
build_datesave=0; // off
|
||||
ret=do_add_file(dllPath,0,0,linecnt,&files_added,tempDLL,2,&data_handle); // 2 means no size add
|
||||
ret=do_add_file(dllPath,0,0,&files_added,tempDLL,2,&data_handle); // 2 means no size add
|
||||
if (ret != PS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -5547,514 +5554,348 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
}
|
||||
|
||||
#ifdef NSIS_SUPPORT_FILE
|
||||
int CEXEBuild::do_add_file(const char *lgss, int attrib, int recurse, int linecnt, int *total_files, const char *name_override, int generatecode, int *data_handle, int rec_depth)
|
||||
int CEXEBuild::do_add_file(const char *lgss, int attrib, int recurse, int *total_files, const char *name_override, int generatecode, int *data_handle, string& basedir)
|
||||
{
|
||||
char dir[1024];
|
||||
char newfn[1024];
|
||||
#ifdef _WIN32
|
||||
HANDLE h;
|
||||
WIN32_FIND_DATA d;
|
||||
#else
|
||||
glob_t globbuf;
|
||||
#endif
|
||||
strcpy(dir,lgss);
|
||||
{
|
||||
char *s=dir+strlen(dir);
|
||||
while (s > dir && *s != PLATFORM_PATH_SEPARATOR_C) s=CharPrev(dir,s);
|
||||
if (s == dir)
|
||||
{
|
||||
if (*s == PLATFORM_PATH_SEPARATOR_C)
|
||||
sprintf(dir,"%c.",PLATFORM_PATH_SEPARATOR_C);
|
||||
else
|
||||
strcpy(dir,".");
|
||||
}
|
||||
else
|
||||
s[0]=0;
|
||||
assert(!name_override || !recurse);
|
||||
|
||||
string dir = get_dir_name(lgss);
|
||||
string spec;
|
||||
|
||||
if (dir == lgss) {
|
||||
dir = ".";
|
||||
spec = lgss;
|
||||
} else {
|
||||
spec = string(lgss).substr(dir.length() + 1, string::npos);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
h = FindFirstFile(lgss,&d);
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
{
|
||||
#else
|
||||
GLOB(lgss, GLOB_NOSORT, NULL, &globbuf);
|
||||
{
|
||||
for (unsigned int i = 0; i < globbuf.gl_pathc; i++)
|
||||
{
|
||||
struct stat s;
|
||||
if (!stat(globbuf.gl_pathv[i], &s) && S_ISREG(s.st_mode))
|
||||
{
|
||||
char *filename = strrchr(globbuf.gl_pathv[i], PLATFORM_PATH_SEPARATOR_C);
|
||||
if (filename)
|
||||
filename++;
|
||||
else
|
||||
filename = globbuf.gl_pathv[i];
|
||||
#endif
|
||||
MMapFile mmap;
|
||||
DWORD len;
|
||||
(*total_files)++;
|
||||
|
||||
#ifdef _WIN32
|
||||
sprintf(newfn,"%s%s%s",dir,dir[0]?PLATFORM_PATH_SEPARATOR_STR:"",d.cFileName);
|
||||
HANDLE hFile = CreateFile(
|
||||
newfn,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
NULL
|
||||
);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose(h);
|
||||
ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
// Will auto-CloseHandle hFile
|
||||
MANAGE_WITH(hFile, CloseHandle);
|
||||
|
||||
len = GetFileSize(hFile, NULL);
|
||||
if (len && !mmap.setfile(hFile, len))
|
||||
{
|
||||
FindClose(h);
|
||||
ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
#else
|
||||
sprintf(newfn,"%s%s%s",dir,dir[0]?PLATFORM_PATH_SEPARATOR_STR:"",filename);
|
||||
len = (DWORD) s.st_size;
|
||||
|
||||
int fd = OPEN(newfn, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
globfree(&globbuf);
|
||||
ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
// Will auto-close(2) fd
|
||||
MANAGE_WITH(fd, close);
|
||||
|
||||
if (len && !mmap.setfile(fd, len))
|
||||
{
|
||||
globfree(&globbuf);
|
||||
ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (generatecode&1)
|
||||
section_add_size_kb((len+1023)/1024);
|
||||
#ifdef _WIN32
|
||||
if (name_override) SCRIPT_MSG("%sFile: \"%s\"->\"%s\"",generatecode?"":"Reserve",d.cFileName,name_override);
|
||||
else SCRIPT_MSG("%sFile: \"%s\"",generatecode?"":"Reserve",d.cFileName);
|
||||
#else
|
||||
if (name_override) SCRIPT_MSG("%sFile: \"%s\"->\"%s\"",generatecode?"":"Reserve",filename,name_override);
|
||||
else SCRIPT_MSG("%sFile: \"%s\"",generatecode?"":"Reserve",filename);
|
||||
#endif
|
||||
if (!build_compress_whole)
|
||||
if (build_compress) SCRIPT_MSG(" [compress]");
|
||||
fflush(stdout);
|
||||
char buf[1024];
|
||||
int last_build_datablock_used=getcurdbsize();
|
||||
entry ent={0,};
|
||||
if (generatecode)
|
||||
{
|
||||
ent.which=EW_EXTRACTFILE;
|
||||
|
||||
DefineInnerLangString(NLF_SKIPPED);
|
||||
DefineInnerLangString(NLF_ERR_DECOMPRESSING);
|
||||
DefineInnerLangString(NLF_ERR_WRITING);
|
||||
DefineInnerLangString(NLF_EXTRACT);
|
||||
DefineInnerLangString(NLF_CANT_WRITE);
|
||||
|
||||
ent.offsets[0]=build_overwrite;
|
||||
if (name_override)
|
||||
{
|
||||
ent.offsets[1]=add_string(name_override);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char *i=d.cFileName,*o=buf;
|
||||
#else
|
||||
char *i=filename,*o=buf;
|
||||
#endif
|
||||
while (*i)
|
||||
{
|
||||
char c=*i++;
|
||||
*o++=c;
|
||||
if (c == '$') *o++='$';
|
||||
}
|
||||
*o=0;
|
||||
ent.offsets[1]=add_string(buf);
|
||||
}
|
||||
}
|
||||
ent.offsets[2]=add_db_data(&mmap);
|
||||
|
||||
mmap.clear();
|
||||
|
||||
if (ent.offsets[2] < 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
if (data_handle)
|
||||
{
|
||||
*data_handle=ent.offsets[2];
|
||||
}
|
||||
|
||||
{
|
||||
DWORD s=getcurdbsize()-last_build_datablock_used;
|
||||
if (s) s-=4;
|
||||
if (s != len) SCRIPT_MSG(" %d/%d bytes\n",s,len);
|
||||
else SCRIPT_MSG(" %d bytes\n",len);
|
||||
}
|
||||
|
||||
if (generatecode)
|
||||
{
|
||||
if (build_datesave || build_overwrite>=0x3 /*ifnewer or ifdiff*/)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILETIME ft;
|
||||
if (GetFileTime(hFile,NULL,NULL,&ft))
|
||||
{
|
||||
ent.offsets[3]=ft.dwLowDateTime;
|
||||
ent.offsets[4]=ft.dwHighDateTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
FindClose(h);
|
||||
#else
|
||||
struct stat st;
|
||||
if (!fstat(fd, &st))
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
long l;
|
||||
long h;
|
||||
} words;
|
||||
long long ll;
|
||||
};
|
||||
ll = (st.st_mtime * 10000000LL) + 116444736000000000LL;
|
||||
ent.offsets[3] = words.l;
|
||||
ent.offsets[4] = words.h;
|
||||
}
|
||||
else
|
||||
{
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
ERROR_MSG("%sFile: failed getting file date from \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ent.offsets[3]=0xffffffff;
|
||||
ent.offsets[4]=0xffffffff;
|
||||
}
|
||||
|
||||
// overwrite flag can be 0, 1, 2 or 3. in all cases, 2 bits
|
||||
int mb = 0;
|
||||
if (build_allowskipfiles)
|
||||
{
|
||||
mb = MB_ABORTRETRYIGNORE | MB_ICONSTOP;
|
||||
// default for silent installers
|
||||
mb |= IDIGNORE << 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
mb = MB_RETRYCANCEL | MB_ICONSTOP;
|
||||
// default for silent installers
|
||||
mb |= IDCANCEL << 20;
|
||||
}
|
||||
ent.offsets[0] |= mb << 3;
|
||||
|
||||
ent.offsets[5] = DefineInnerLangString(build_allowskipfiles ? NLF_FILE_ERROR : NLF_FILE_ERROR_NOIGNORE);
|
||||
}
|
||||
|
||||
if (generatecode)
|
||||
{
|
||||
int a=add_entry(&ent);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
return a;
|
||||
}
|
||||
if (attrib)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ent.which=EW_SETFILEATTRIBUTES;
|
||||
// $OUTDIR is the working directory
|
||||
ent.offsets[0]=add_string(name_override?name_override:buf);
|
||||
ent.offsets[1]=d.dwFileAttributes;
|
||||
ent.offsets[2]=0;
|
||||
ent.offsets[3]=0;
|
||||
ent.offsets[4]=0;
|
||||
ent.offsets[5]=0;
|
||||
|
||||
a=add_entry(&ent);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
FindClose(h);
|
||||
return a;
|
||||
}
|
||||
#else
|
||||
warning_fl("File /a is disabled for non Win32 platforms.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
while (FindNextFile(h,&d));
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
if (spec == "") {
|
||||
spec = "*";
|
||||
}
|
||||
|
||||
if (recurse)
|
||||
{
|
||||
#ifdef NSIS_SUPPORT_STACK
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA temp;
|
||||
#endif
|
||||
dir_reader *dr = new_dir_reader();
|
||||
dr->read(dir);
|
||||
|
||||
const char *fspec;
|
||||
if (!strcmp(dir,".") && strncmp(lgss,".",1))
|
||||
fspec=lgss;
|
||||
else
|
||||
fspec=lgss+strlen(dir)+!!dir[0];
|
||||
dir_reader::iterator files_itr = dr->files().begin();
|
||||
dir_reader::iterator files_end = dr->files().end();
|
||||
|
||||
strcpy(newfn,lgss);
|
||||
#ifdef _WIN32
|
||||
DWORD a=GetFileAttributes(lgss);
|
||||
if (a==INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
a=GetFileAttributes(dir);
|
||||
sprintf(newfn,"%s%s*.*",dir,dir[0]?PLATFORM_PATH_SEPARATOR_STR:"");
|
||||
}
|
||||
#else
|
||||
int a;
|
||||
struct stat st;
|
||||
if (stat(lgss, &st))
|
||||
{
|
||||
stat(dir, &st);
|
||||
sprintf(newfn,"%s%s*",dir,dir[0]?PLATFORM_PATH_SEPARATOR_STR:"");
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
// we don't want to include a whole directory if it's not the first call
|
||||
if (rec_depth) return PS_OK;
|
||||
#ifdef _WIN32
|
||||
fspec="*.*";
|
||||
#else
|
||||
fspec="*";
|
||||
#endif
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (a&FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
h=FindFirstFile(newfn,&d);
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (strcmp(d.cFileName,"..") && strcmp(d.cFileName,"."))
|
||||
{
|
||||
#else
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
if (!GLOB(newfn, GLOB_NOSORT, NULL, &globbuf))
|
||||
{
|
||||
for (unsigned int i = 0; i < globbuf.gl_pathc; i++)
|
||||
{
|
||||
struct stat s;
|
||||
if (!stat(globbuf.gl_pathv[i], &s) && S_ISDIR(s.st_mode))
|
||||
{
|
||||
char *dirname = strrchr(globbuf.gl_pathv[i], PLATFORM_PATH_SEPARATOR_C);
|
||||
if (dirname)
|
||||
dirname++;
|
||||
else
|
||||
dirname = globbuf.gl_pathv[i];
|
||||
if (strcmp(dirname, "..") && strcmp(dirname, "."))
|
||||
{
|
||||
#endif
|
||||
char out_path[1024] = "$OUTDIR\\";
|
||||
bool dir_created = false;
|
||||
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char *i = d.cFileName;
|
||||
#else
|
||||
char *i = dirname;
|
||||
#endif
|
||||
char *o=out_path+strlen(out_path);
|
||||
if (basedir == "") {
|
||||
dir_created = true;
|
||||
|
||||
while (*i)
|
||||
{
|
||||
char *ni=CharNext(i);
|
||||
if (ni-i > 1)
|
||||
{
|
||||
int l=ni-i;
|
||||
while (l--)
|
||||
{
|
||||
*o++=*i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char c=*i++;
|
||||
*o++=c;
|
||||
if (c == '$') *o++='$';
|
||||
}
|
||||
}
|
||||
*o=0;
|
||||
}
|
||||
|
||||
char spec[1024];
|
||||
#ifdef _WIN32
|
||||
wsprintf(spec,"%s%s%s",dir,dir[0]?PLATFORM_PATH_SEPARATOR_STR:"",d.cFileName);
|
||||
#else
|
||||
wsprintf(spec,"%s%s%s",dir,dir[0]?PLATFORM_PATH_SEPARATOR_STR:"",dirname);
|
||||
#endif
|
||||
SCRIPT_MSG("%sFile: Descending to: \"%s\"\n",generatecode?"":"Reserve",spec);
|
||||
strcat(spec,PLATFORM_PATH_SEPARATOR_STR);
|
||||
strcat(spec,fspec);
|
||||
if (generatecode)
|
||||
{
|
||||
a=add_entry_direct(EW_PUSHPOP, add_string("$OUTDIR"));
|
||||
if (a != PS_OK)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
return a;
|
||||
}
|
||||
|
||||
a=add_entry_direct(EW_ASSIGNVAR, m_UserVarNames.get("OUTDIR"), add_string(out_path));
|
||||
if (a != PS_OK)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
return a;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE htemp = FindFirstFile(spec,&temp);
|
||||
if (htemp != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose(htemp);
|
||||
#else
|
||||
glob_t globbuf2;
|
||||
GLOB(spec, GLOB_NOSORT, NULL, &globbuf2);
|
||||
if (globbuf2.gl_pathc)
|
||||
{
|
||||
#endif
|
||||
|
||||
a=add_entry_direct(EW_CREATEDIR, add_string("$OUTDIR"), 1);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf2);
|
||||
#endif
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
a=do_add_file(spec,attrib,recurse,linecnt,total_files,NULL,generatecode,data_handle,rec_depth+1);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
return a;
|
||||
}
|
||||
|
||||
if (generatecode)
|
||||
{
|
||||
a=add_entry_direct(EW_PUSHPOP, m_UserVarNames.get("OUTDIR"), 1);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
return a;
|
||||
}
|
||||
|
||||
if (attrib)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
a=add_entry_direct(EW_SETFILEATTRIBUTES, add_string(out_path), d.dwFileAttributes);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
FindClose(h);
|
||||
return a;
|
||||
}
|
||||
#else
|
||||
warning_fl("File /a is disabled for non Win32 platforms.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
SCRIPT_MSG("%sFile: Returning to: \"%s\"\n",generatecode?"":"Reserve",dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
while (FindNextFile(h,&d));
|
||||
FindClose(h);
|
||||
#else
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
|
||||
if (!rec_depth)
|
||||
{
|
||||
// return to the original $OUTDIR
|
||||
a=add_entry_direct(EW_CREATEDIR, add_string("$OUTDIR"), 1);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
}
|
||||
if (recurse) {
|
||||
// save $OUTDIR into $0
|
||||
if (add_entry_direct(EW_ASSIGNVAR, m_UserVarNames.get("0"), add_string("$OUTDIR")) != PS_OK) {
|
||||
delete dr;
|
||||
return PS_ERROR;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ERROR_MSG("Error: recursive [Reserve]File requires NSIS_SUPPORT_STACK\n");
|
||||
}
|
||||
|
||||
for (; files_itr != files_end; files_itr++) {
|
||||
if (!dir_reader::matches(*files_itr, spec))
|
||||
continue;
|
||||
|
||||
if (!dir_created && generatecode) {
|
||||
SCRIPT_MSG("%sFile: Descending to: \"%s\"\n", generatecode? "" : "Reserve", dir.c_str());
|
||||
|
||||
if (do_add_file_create_dir(dir, basedir, attrib) != PS_OK) {
|
||||
delete dr;
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
dir_created = true;
|
||||
}
|
||||
|
||||
if (add_file(dir, *files_itr, attrib, name_override, generatecode, data_handle) != PS_OK) {
|
||||
delete dr;
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
(*total_files)++;
|
||||
}
|
||||
|
||||
if (recurse) {
|
||||
dir_reader::iterator dirs_itr = dr->dirs().begin();
|
||||
dir_reader::iterator dirs_end = dr->dirs().end();
|
||||
|
||||
for (; dirs_itr != dirs_end; dirs_itr++) {
|
||||
string new_dir;
|
||||
|
||||
if (basedir == "") {
|
||||
new_dir = *dirs_itr;
|
||||
} else {
|
||||
new_dir = basedir + PLATFORM_PATH_SEPARATOR_STR + *dirs_itr;
|
||||
}
|
||||
|
||||
string new_spec = dir + PLATFORM_PATH_SEPARATOR_STR + *dirs_itr + PLATFORM_PATH_SEPARATOR_STR;
|
||||
|
||||
if (!dir_reader::matches(*dirs_itr, spec)) {
|
||||
new_spec += spec;
|
||||
}
|
||||
|
||||
const char *new_spec_c = new_spec.c_str();
|
||||
|
||||
if (do_add_file(new_spec_c, attrib, 1, total_files, NULL, generatecode, NULL, new_dir) != PS_OK) {
|
||||
delete dr;
|
||||
return PS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (basedir == "") {
|
||||
SCRIPT_MSG("%sFile: Returning to: \"%s\"\n", generatecode ? "" : "Reserve", dir.c_str());
|
||||
|
||||
// restore $OUTDIR from $0
|
||||
if (do_add_file_create_dir(dir, basedir) != PS_OK) {
|
||||
delete dr;
|
||||
return PS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete dr;
|
||||
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
int CEXEBuild::add_file(const string& dir, const string& file, int attrib, const char *name_override, int generatecode, int *data_handle) {
|
||||
string newfn_s = dir + PLATFORM_PATH_SEPARATOR_C + file;
|
||||
const char *newfn = newfn_s.c_str();
|
||||
const char *filename = file.c_str();
|
||||
|
||||
MMapFile mmap;
|
||||
DWORD len;
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE hFile = CreateFile(
|
||||
newfn,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
NULL
|
||||
);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
// Will auto-CloseHandle hFile
|
||||
MANAGE_WITH(hFile, CloseHandle);
|
||||
|
||||
len = GetFileSize(hFile, NULL);
|
||||
if (len && !mmap.setfile(hFile, len))
|
||||
{
|
||||
ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
#else
|
||||
struct stat s;
|
||||
if (stat(newfn, &s)) {
|
||||
ERROR_MSG("%sFile: failed stating file \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
len = (DWORD) s.st_size;
|
||||
|
||||
int fd = OPEN(newfn, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
// Will auto-close(2) fd
|
||||
MANAGE_WITH(fd, close);
|
||||
|
||||
if (len && !mmap.setfile(fd, len))
|
||||
{
|
||||
ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (generatecode&1)
|
||||
section_add_size_kb((len+1023)/1024);
|
||||
if (name_override) SCRIPT_MSG("%sFile: \"%s\"->\"%s\"",generatecode?"":"Reserve",filename,name_override);
|
||||
else SCRIPT_MSG("%sFile: \"%s\"",generatecode?"":"Reserve",filename);
|
||||
if (!build_compress_whole)
|
||||
if (build_compress) SCRIPT_MSG(" [compress]");
|
||||
fflush(stdout);
|
||||
char buf[1024];
|
||||
int last_build_datablock_used=getcurdbsize();
|
||||
entry ent={0,};
|
||||
if (generatecode)
|
||||
{
|
||||
ent.which=EW_EXTRACTFILE;
|
||||
|
||||
DefineInnerLangString(NLF_SKIPPED);
|
||||
DefineInnerLangString(NLF_ERR_DECOMPRESSING);
|
||||
DefineInnerLangString(NLF_ERR_WRITING);
|
||||
DefineInnerLangString(NLF_EXTRACT);
|
||||
DefineInnerLangString(NLF_CANT_WRITE);
|
||||
|
||||
ent.offsets[0]=build_overwrite;
|
||||
if (name_override)
|
||||
{
|
||||
ent.offsets[1]=add_string(name_override);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *i=filename;
|
||||
char *o=buf;
|
||||
while (*i)
|
||||
{
|
||||
const char c=*i++;
|
||||
*o++=c;
|
||||
if (c == '$') *o++='$';
|
||||
}
|
||||
*o=0;
|
||||
ent.offsets[1]=add_string(buf);
|
||||
}
|
||||
}
|
||||
ent.offsets[2]=add_db_data(&mmap);
|
||||
|
||||
mmap.clear();
|
||||
|
||||
if (ent.offsets[2] < 0)
|
||||
{
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
if (data_handle)
|
||||
{
|
||||
*data_handle=ent.offsets[2];
|
||||
}
|
||||
|
||||
{
|
||||
DWORD s=getcurdbsize()-last_build_datablock_used;
|
||||
if (s) s-=4;
|
||||
if (s != len) SCRIPT_MSG(" %d/%d bytes\n",s,len);
|
||||
else SCRIPT_MSG(" %d bytes\n",len);
|
||||
}
|
||||
|
||||
if (generatecode)
|
||||
{
|
||||
if (build_datesave || build_overwrite>=0x3 /*ifnewer or ifdiff*/)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILETIME ft;
|
||||
if (GetFileTime(hFile,NULL,NULL,&ft))
|
||||
{
|
||||
ent.offsets[3]=ft.dwLowDateTime;
|
||||
ent.offsets[4]=ft.dwHighDateTime;
|
||||
}
|
||||
#else
|
||||
struct stat st;
|
||||
if (!fstat(fd, &st))
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
long l;
|
||||
long h;
|
||||
} words;
|
||||
long long ll;
|
||||
};
|
||||
ll = (st.st_mtime * 10000000LL) + 116444736000000000LL;
|
||||
ent.offsets[3] = words.l;
|
||||
ent.offsets[4] = words.h;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
ERROR_MSG("%sFile: failed getting file date from \"%s\"\n",generatecode?"":"Reserve",newfn);
|
||||
return PS_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ent.offsets[3]=0xffffffff;
|
||||
ent.offsets[4]=0xffffffff;
|
||||
}
|
||||
|
||||
// overwrite flag can be 0, 1, 2 or 3. in all cases, 2 bits
|
||||
int mb = 0;
|
||||
if (build_allowskipfiles)
|
||||
{
|
||||
mb = MB_ABORTRETRYIGNORE | MB_ICONSTOP;
|
||||
// default for silent installers
|
||||
mb |= IDIGNORE << 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
mb = MB_RETRYCANCEL | MB_ICONSTOP;
|
||||
// default for silent installers
|
||||
mb |= IDCANCEL << 20;
|
||||
}
|
||||
ent.offsets[0] |= mb << 3;
|
||||
|
||||
ent.offsets[5] = DefineInnerLangString(build_allowskipfiles ? NLF_FILE_ERROR : NLF_FILE_ERROR_NOIGNORE);
|
||||
}
|
||||
|
||||
if (generatecode)
|
||||
{
|
||||
int a=add_entry(&ent);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
if (attrib)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ent.which=EW_SETFILEATTRIBUTES;
|
||||
// $OUTDIR is the working directory
|
||||
ent.offsets[0]=add_string(name_override?name_override:buf);
|
||||
ent.offsets[1]=GetFileAttributes(newfn);
|
||||
ent.offsets[2]=0;
|
||||
ent.offsets[3]=0;
|
||||
ent.offsets[4]=0;
|
||||
ent.offsets[5]=0;
|
||||
|
||||
a=add_entry(&ent);
|
||||
if (a != PS_OK)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
int CEXEBuild::do_add_file_create_dir(const string& local_dir, const string& dir, int attrib) {
|
||||
string outdir_s = "$0\\" + dir;
|
||||
|
||||
string::size_type pos = 1;
|
||||
pos = outdir_s.find('$', pos);
|
||||
while (pos != string::npos) {
|
||||
outdir_s = outdir_s.insert(pos, "$");
|
||||
pos = outdir_s.find('$', pos + 2);
|
||||
}
|
||||
|
||||
int outdir = add_string(outdir_s.c_str());
|
||||
|
||||
if (add_entry_direct(EW_CREATEDIR, outdir, 1) != PS_OK) {
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (attrib) {
|
||||
int ndc = add_string(".");
|
||||
|
||||
DWORD attr = GetFileAttributes(local_dir.c_str());
|
||||
|
||||
if (add_entry_direct(EW_SETFILEATTRIBUTES, ndc, attr) != PS_OK) {
|
||||
return PS_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return PS_OK;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue