ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Distribution: Ubuntu n' Flavors, ReactOS, MINIX3, FreeDOS, Arch
Posts: 339
Rep:
Make a self extractor
OK, I want o make a self extractor(C++)(CLI).
I know how to use binary fstream but dont know how to put a file in the EXE or how to use it once its in. Can anyone help?
MinGW Compiler
HOw would I write a program to do it for me? (it sounds awesome!)
well, you could probably use od and sed (I found this somewhere)
Code:
(echo "const unsigned char binary_data[] = {"; od -txC -v myfile.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$d" | sed -e"\$s/,$/};/")
in C, on the other hand, it could look like this (yes, I just love doing everything in C/C++ while there are better tools to do it)
Code:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *fpin, *fpout;
int counter = 0;
int c;
if (argc != 3) {
fprintf(stderr, "usage: %s [INPUT FILE] [OUTPUT FILE]", argv[0]);
return 1;
}
fpin = fopen(argv[1], "rb");
if ( ! fpin ) {
fprintf(stderr, "err: could not open file \"%s\" for reading", argv[1]);
return 2;
}
fpout = fopen(argv[2], "w");
if ( ! fpout ) {
fprintf(stderr, "err: could not open file \"%s\" for writing", argv[2]);
fclose(fpin);
return 2;
}
fprintf(fpout, "const unsigned char data[] = {\n");
while ( fread(&c, 1, 1, fpin) ) {
if (counter == 10) { counter = 0; fprintf(fpout, ",\n"); }
fprintf(fpout, counter++ == 0 ? "\t0x%02x" : ", 0x%02x", c);
}
fprintf(fpout, "\n};");
fclose(fpin);
fclose(fpout);
return 0;
}
Could use some improvement, though, such as using a buffer to store the input.
There are probably as many ways of doing this as there are programming languages. You can also try exporting the file as C source from a hex editor or something.
Distribution: Ubuntu n' Flavors, ReactOS, MINIX3, FreeDOS, Arch
Posts: 339
Original Poster
Rep:
I tried that with a rather large file and the output was only 3 bytes (Supposed to be 501 kilos) (the text hexadecimal output thing was fine the actual binary file wasn't)
I know (took a half hour for the precompiler to get done) but any help?
OK, I want o make a self extractor(C++)(CLI).
I know how to use binary fstream but dont know how to put a file in the EXE or how to use it once its in. Can anyone help?
MinGW Compiler
Append file at the end of exe. When program starts, let it read its own header in order to determine actual size of executable code, then open its own executable file, skip number of executable bytes, and read the data. Or store size of exe somewhere within program code as a constant, and patch it with correct value once program has been compiled.
Quote:
Originally Posted by millgates
For large files, that would not be very practical.
For a larger files some compilers may be unable to process the array.
Distribution: Ubuntu n' Flavors, ReactOS, MINIX3, FreeDOS, Arch
Posts: 339
Original Poster
Rep:
Um... Mr.SigTerm I AM NOT DENNIS RITCHIE!!!!! Could you please explain that more clearly? I have no idea how to do almost any of that!
How do I append the file!?!? How do I get the executable's size!?!? ECT!?!?
7zip is an opensource archiver and it has self-extractor module. You could try to see how it works - source code should be available.
Quote:
Originally Posted by Zssfssz
How do I append the file!?!?
You compile self-extractor that contains NO data to be extracted, then open (fopen("program.exe", "wba")) it with external program, seek to the end of file, and write data you want module to unpack into file using fwrite. For that windows platform has "copy /b" shell command and linux has "cat".
When resulting exe launches, it should skip to the beginning of data, and read from it. To do that you need to find file that corresponds to current module and read from it (GetModuleFilename on windows platform), or get a pointer to module as it is loaded into memory (in some versions of windows you could cast GetModuleHandle() result into pointer, but I'm not sure if this is even documented functionality).
The trick is to determine offset of data.
You can try to do that by:
making self-extractor parse its own header (IMAGE_FILE_HEADER on msdn), calculate size of exe, and skip required number of bytes. This is not guaranteed to work, and might be complicated.
(easiest) You could store size of program file within program in global constant variable (static const long programSize = 0 and update this variable after program has been compiled, by opening file, locating required offset and writing new value into it. This is the easiest method. The trick is to locate the variable once program has been compiled. To do so, you could either plase a "marker" around it, or use disassembler to locate it. There might be a better way to do it. If your compiler produces exe of same size during every compilation, then you simply could compile program twice - first time to determine resulting program size, and next time - with correctly set constant value. The problem with this approach is that somebody tries to run "gnu strip" on your program, it most likely will break everything.
Distribution: Ubuntu n' Flavors, ReactOS, MINIX3, FreeDOS, Arch
Posts: 339
Original Poster
Rep:
I have looked at 7zip but I can't find the command line version of it and I just got to diologs In GUI programing. So how would I use the size of the program to determine what to extract? How would I make the program write this data? Is there a easy way to get my IDE (Code::Blocks) to do this for me (as in add file to executable)? Am I hopeless? I loved the first hexadecimal thing (could you give me an outline of what it is doing? I want to port it to C++) but the file I want to try it on is ~500 Kilobytes.
Suppose you want to incorporate string "123" (3 bytes length) to the executable file "a.out". For simplicity I assume that "a.out", when run, just prints to stdout its payload (that is the string 123).
It is not a problem to append "123" to a.out. For example, on linux:
Code:
echo -n "123" >> a.out
(`-n' suppress trailing newline)
Your program should first open its own binary, then seek to 3 bytes back from its end and print contents of the file to the end. To do that your program have to know that its payload is 3 bytes length. This may be specified at compile time.
Here is an example.
Code:
// file self-extract.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#ifndef N
#define N 0
#endif
int main(int argc, char* argv[])
{
int fd = open(argv[0], O_RDONLY);
if (fd == -1)
{
perror("Can't open file\n");
return 1;
}
if (lseek(fd, -N, SEEK_END) == -1)
{
perror("Can't seek\n");
return 1;
}
char buf;
while ( read(fd, &buf, 1) )
{
putchar(buf);
}
return 0;
}
Of course your program can do more complicated things with payload than just printing it. The code may require some modification to compile on Windows.
Hope this helps.
PS. If you don't know how to append to the file, follow SigTerm's suggestion -- use `copy' utility or write your own.
Distribution: Ubuntu n' Flavors, ReactOS, MINIX3, FreeDOS, Arch
Posts: 339
Original Poster
Rep:
How would I seek throughthe file? Would this be easyer in Perl? I know perl but i thought scripted languiges had a weekness in storing binary files in them. (if the file was outside of that then it would be easy.)
I also know minute ammounts of python and ruby (weekest being ruby) but ruby wont start on my computer...
So, how do i seek through the file, and would this be easyer in Perl?
The situation is different for compiled languages (like C) and for interpreted languages (like Perl).
1. In C you write your program in a text file, say `prog.c', then you compile it to binary file, on linux just `prog', and then run it: `./prog' on linux. Executable file is different from program source. In this situation your program (self-extractor) should open its own binary file and locate the payload inside. You need some kind of `seek' function for this. And in C you already have one, it is called `lseek' (in linux you can run `man 2 lseek' for details or see here and this example). In my previous post I use lseek to go to specified number of bytes back from the end of file.
2. There are no such thing as executable (binary) file for interpreted languages. So you don't need to load it and then find something there. Instead you just put the information you want straight to the script, for example using here document and do what you want with it. This approach is very similar to putting the data to C-array (see first post), but much simpler and standard for such languages. In fact, some time ago this approach was used to make self-extracting shell archives (shar) -- see here and here.
Example in perl:
Code:
print << 'END'
Your
data
goes
here
END
Note that here-documents are designed to work with textual data only so binary data will require some preprocessing (like encoding to base64 or to hex format).
Note also that you will need an interpreter (correctly installed perl executable in your case) in order to extract your data automatically.
Hope this helps.
Last edited by firstfire; 11-21-2011 at 11:16 PM.
Reason: fix a typo
Distribution: Ubuntu n' Flavors, ReactOS, MINIX3, FreeDOS, Arch
Posts: 339
Original Poster
Rep:
This pice of info might also chage some things:
The file is a non OS/2\Windows specific DLL. I wrote it and have the endure source (der).
Would it be possible to place the code inside of a variable or something and when it's comPiled it gets turned into binary data.
I acctualy have both strawberrie and ActiveState perl on my computer (the Linux side doesnt have one because I dont have Internet nor the time to to download all dependicys). Still deciding which one get in the regishtry and path... They both have ups n downs.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.