diff options
Diffstat (limited to 'exec/exec.c')
-rw-r--r-- | exec/exec.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/exec/exec.c b/exec/exec.c index 6a78f89f..6e83108f 100644 --- a/exec/exec.c +++ b/exec/exec.c @@ -10,6 +10,9 @@ Can exec any executable format the BFD library understands to be for this flavor of machine. #endif + #ifdef BZIP2 + Can bunzip2 executables into core on the fly. + #endif This file is part of the GNU Hurd. @@ -69,6 +72,10 @@ b2he (error_t deflt) static void check_gzip (struct execdata *); #endif +#ifdef BZIP2 +static void check_bzip2 (struct execdata *); +#endif + #ifdef BFD /* Check a section, updating the `locations' vector [BFD]. */ @@ -1031,6 +1038,98 @@ check_gzip (struct execdata *earg) e->stream.__seen = 1; } #endif + +#ifdef BZIP2 +/* Check the file for being a bzip2'd image. Return with ENOEXEC means not + a valid bzip2 file; return with another error means lossage in decoding; + return with zero means the file was uncompressed into memory which E now + points to, and `check' can be run again. */ + +static void +check_bzip2 (struct execdata *earg) +{ + struct execdata *e = earg; + /* Entry points to bunzip2 engine. */ + void do_bunzip2 (void); + /* Callbacks from unzip for I/O and error interface. */ + extern int (*unzip_read) (char *buf, size_t maxread); + extern void (*unzip_write) (const char *buf, size_t nwrite); + extern void (*unzip_read_error) (void); + extern void (*unzip_error) (const char *msg); + + char *zipdata = NULL; + size_t zipdatasz = 0; + FILE *zipout = NULL; + jmp_buf ziperr; + int zipread (char *buf, size_t maxread) + { + return fread (buf, 1, maxread, &e->stream); + } + void zipwrite (const char *buf, size_t nwrite) + { + if (fwrite (buf, nwrite, 1, zipout) != 1) + longjmp (ziperr, 1); + } + void ziprderr (void) + { + errno = ENOEXEC; + longjmp (ziperr, 2); + } + void ziperror (const char *msg) + { + errno = ENOEXEC; + longjmp (ziperr, 2); + } + + unzip_read = zipread; + unzip_write = zipwrite; + unzip_read_error = ziprderr; + unzip_error = ziperror; + + if (setjmp (ziperr)) + { + /* Error in unzipping jumped out. */ + if (zipout) + { + fclose (zipout); + free (zipdata); + } + e->error = errno; + return; + } + + rewind (&e->stream); + + zipout = open_memstream (&zipdata, &zipdatasz); + if (! zipout) + { + e->error = errno; + return; + } + + /* Call the bunzip2 engine. */ + do_bunzip2 (); + + /* The output is complete. Clean up the stream and store its resultant + buffer and size in the execdata as the file contents. */ + fclose (zipout); + e->file_data = zipdata; + e->file_size = zipdatasz; + + /* Clean up the old exec file stream's state. */ + finish (e, 0); + + /* Point the stream at the buffer of file data. */ + memset (&e->stream, 0, sizeof (e->stream)); + e->stream.__magic = _IOMAGIC; + e->stream.__mode.__read = 1; + e->stream.__buffer = e->file_data; + e->stream.__bufsize = e->file_size; + e->stream.__get_limit = e->stream.__buffer + e->stream.__bufsize; + e->stream.__bufp = e->stream.__buffer; + e->stream.__seen = 1; +} +#endif static inline error_t @@ -1099,6 +1198,7 @@ do_exec (file_t file, /* The gzip code is really cheesy, not even close to thread-safe. So we serialize all uses of it. */ mutex_lock (&lock); + e->error = 0; check_gzip (e); mutex_unlock (&lock); if (e->error == 0) @@ -1108,6 +1208,24 @@ do_exec (file_t file, check (e); } #endif +#ifdef BZIP2 + if (e->error == ENOEXEC) + { + /* See if it is a compressed image. */ + static struct mutex lock = MUTEX_INITIALIZER; + /* The bzip2 code is really cheesy, not even close to thread-safe. + So we serialize all uses of it. */ + mutex_lock (&lock); + e->error = 0; + check_bzip2 (e); + mutex_unlock (&lock); + if (e->error == 0) + /* The file was uncompressed into memory, and now E describes the + uncompressed image rather than the actual file. Check it again + for a valid magic number. */ + check (e); + } +#endif } |