PAR-Packer
view release on metacpan or search on metacpan
myldr/mktmpdir.c view on Meta::CPAN
#ifndef P_tmpdir
#define P_tmpdir "/tmp"
#endif
/* NOTE: This code is #include'd both from a plain C program (boot.c)
* and our custom Perl interpreter (main.c). In the latter case,
* lstat() or stat() may be #define'd as calls into PerlIO and
* expect pointer to a Stat_t as second parameter, rather than a pointer
* to a struct stat. Try to distinguish these cases by checking
* whether Stat_t is defined. */
#ifndef Stat_t
#define Stat_t struct stat
#endif
static char PAR_MAGIC[] = "\nPAR.pm\n";
#define magic_size 8
/* "\0CACHE" or "\0CLEAN" */
#define cache_marker_size 6
/* size of a pack("N") number */
#define FILE_offset_size 4
#define cache_name_size 40
#define CHECK(code, msg) if (!(code)) { par_die(msg); }
static int isWritableDir(const char* val)
{
Stat_t statbuf;
return par_lstat(val, &statbuf) == 0 &&
( S_ISDIR(statbuf.st_mode) || S_ISLNK(statbuf.st_mode) ) &&
access(val, W_OK) == 0;
}
#ifndef WIN32
/* check that:
* - val is a directory (and not a symlink)
* - val is owned by the user
* - val has mode 0700
*/
static int isSafeDir(const char* val)
{
Stat_t statbuf;
return par_lstat(val, &statbuf) == 0 &&
S_ISDIR(statbuf.st_mode) &&
statbuf.st_uid == getuid() &&
(statbuf.st_mode & 0777) == 0700;
}
#endif
void par_setup_libpath( const char * stmpdir )
{
const char *ldlibpthname = stringify(LDLIBPTHNAME);
const char *val;
if ( (val = par_getenv(ldlibpthname)) == NULL || strlen(val) == 0 ) {
par_setenv(ldlibpthname, stmpdir);
}
else {
/* prepend stmpdir to (value of) environment variable */
char *new_val = malloc(
strlen(stmpdir) + strlen(path_sep) + strlen(val) + 1);
sprintf(
new_val, "%s%s%s",
stmpdir, path_sep, val);
par_setenv(ldlibpthname, new_val);
}
}
static void *par_memrmem(void* haystack, size_t haystacklen, void* needle, size_t needlelen)
{
char *hs = haystack;
char *p;
if (haystacklen < needlelen)
return NULL;
for (p = hs + haystacklen - needlelen; p >= hs; p--)
if (memcmp(p, needle, needlelen) == 0)
return p;
return NULL;
}
static off_t find_par_magic(int fd)
{
#define CHUNK_SIZE (64 * 1024)
char buf[CHUNK_SIZE + magic_size];
off_t pos;
int len;
char *p;
off_t file_size = lseek(fd, 0, 2);
for (pos = (file_size-1) - (file_size-1) % CHUNK_SIZE;
pos >= 0;
pos -= CHUNK_SIZE) {
CHECK(lseek(fd, pos, 0) != -1, "lseek failed");
len = read(fd, buf, CHUNK_SIZE + magic_size);
CHECK(len != -1, "read failed");
p = par_memrmem(buf, len, PAR_MAGIC, magic_size);
if (p)
return pos + (p - buf);
}
return -1;
#undef CHUNK_SIZE
}
char *par_mktmpdir ( char **argv ) {
int i;
const char *tmpdir = NULL;
const char *key = NULL , *val = NULL;
/* NOTE: all arrays below are NULL terminated */
const char *temp_dirs[] = {
P_tmpdir,
#ifdef WIN32
"C:\\TEMP",
#endif
".", NULL };
const char *temp_keys[] = { "PAR_TMPDIR", "TMPDIR", "TEMPDIR",
"TEMP", "TMP", NULL };
const char *user_keys[] = { "USER", "USERNAME", NULL };
const char *subdirbuf_prefix = "par-";
const char *subdirbuf_suffix = "";
char *progname = NULL, *username = NULL;
char *stmpdir = NULL, *top_tmpdir = NULL;
int f, stmp_len = 0;
myldr/mktmpdir.c view on Meta::CPAN
if (progname == NULL)
progname = argv[0];
/* If invoked as "/usr/bin/parl foo.par myscript.pl" then progname should
* be ".../parl", and we don't want to base our checksum on that, but
* rather on "foo.par".
*/
{
#ifdef WIN32
#define STREQ(a,b) (strcasecmp(a,b) == 0)
#else
#define STREQ(a,b) (strcmp(a,b) == 0)
#endif
const char *parl_exe = stringify(PARL_EXE);
int prog_len = strlen(progname);
int parl_len = strlen(parl_exe);
if (prog_len >= parl_len
&& STREQ(progname + prog_len - parl_len, parl_exe)
&& (prog_len == parl_len || progname[prog_len - parl_len - 1] == dir_sep[0])
&& argv[1]
&& strlen(argv[1]) >= 4
&& STREQ(argv[1] + strlen(argv[1]) - 4, ".par"))
progname = argv[1];
#undef STREQ
}
int use_cache = 0;
if ( !par_env_clean() && (f = open( progname, O_RDONLY | OPEN_O_BINARY ))) {
off_t pos = find_par_magic(f);
char buf[cache_marker_size];
if (pos >= 0) {
/* back up over pack(N) number and "\0CACHE" (or "\0CLEAN") */
pos -= FILE_offset_size + cache_marker_size;
lseek(f, pos, 0);
CHECK(read(f, buf, cache_marker_size) == cache_marker_size, "short read");
if (memcmp(buf, "\0CACHE", cache_marker_size) == 0) {
use_cache = 1;
/* back up over pre-computed cache_name */
pos -= cache_name_size;
lseek(f, pos, 0);
CHECK(read(f, sha1, cache_name_size) == cache_name_size, "short read");
sha1[cache_name_size] = '\0';
}
else if (memcmp(buf, "\0CLEAN", cache_marker_size) == 0) {
use_cache = 0;
}
}
}
if (use_cache) {
/* "$TEMP/par-$USER/cache-$SHA1" */
sprintf(
stmpdir,
"%s%scache-%s%s",
top_tmpdir, dir_sep, sha1, subdirbuf_suffix
);
}
else {
/* "$TEMP/par-$USER/temp-$PID" */
par_setenv("PAR_CLEAN", "1");
sprintf(
stmpdir,
"%s%stemp-%u%s",
top_tmpdir, dir_sep, getpid(), subdirbuf_suffix
);
/* Ensure we pick an unused directory each time. If the directory
already exists when we try to create it, bump a counter and try
"$TEMP/par-$USER/temp-$PID-$i". This will guard against cases where
a prior invocation crashed leaving garbage in a temp directory that
might interfere. */
int i = 0;
while (my_mkdir(stmpdir, 0700) == -1 && errno == EEXIST) {
sprintf(
stmpdir,
"%s%stemp-%u-%u%s",
top_tmpdir, dir_sep, getpid(), ++i, subdirbuf_suffix
);
}
}
free(top_tmpdir);
/* set dynamic loading path */
par_setenv("PAR_TEMP", stmpdir);
par_setup_libpath( stmpdir );
return stmpdir;
}
#ifdef WIN32
static void par_rmtmpdir ( char *stmpdir ) {
struct _finddata_t cur_file;
int subsub_len;
char *subsubdir;
char *slashdot;
intptr_t hFile;
int tries = 0;
HMODULE dll;
if ((stmpdir == NULL) || !strlen(stmpdir)) return;
subsub_len = strlen(stmpdir) + 258;
subsubdir = malloc( subsub_len );
sprintf(subsubdir, "%s\\*.*", stmpdir);
hFile = _findfirst( subsubdir, &cur_file );
if ( hFile == -1 ) return;
do {
if (!strstr(cur_file.name, "\\")) {
sprintf(subsubdir, "%s\\%s", stmpdir, cur_file.name);
}
else {
sprintf(subsubdir, "%s", cur_file.name);
}
if (!(slashdot = strstr(subsubdir, "\\.")) || (strcmp(slashdot,"\\.") && strcmp(slashdot,"\\.."))) {
if ((cur_file.attrib & _A_SUBDIR)) {
par_rmtmpdir( subsubdir );
}
else {
dll = GetModuleHandle(cur_file.name);
tries = 0;
while ( _unlink(subsubdir) && ( tries++ < 10 ) ) {
if ( dll ) FreeLibrary(dll);
};
}
}
} while ( _findnext( hFile, &cur_file ) == 0 );
_findclose(hFile);
_rmdir(stmpdir);
}
#else
static void par_rmtmpdir ( char *stmpdir ) {
DIR *partmp_dirp;
Direntry_t *dp;
char *subsubdir = NULL;
int subsub_len;
Stat_t stbuf;
( run in 1.162 second using v1.01-cache-2.11-cpan-6aa56a78535 )