Why program in C won't work on Windows? - c

I have a program written in Linux in C, and it works well on Linux platform, but it doesn't work in Windows. It compiles successfully in Windows, using Code Blocks(mingw32-gcc), but it doesn't work as expected, it simply throws an error and kills the program. How can I make it to work on Windows, Please help. This is the code:
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i, size, k = 2, ftab, sect = 3;
char buf[512];
char vbuf;
int dev, fil_descr, off=0;
fil_descr = open(argv[2], O_RDONLY);
assert(fil_descr > 0);
read(fil_descr, buf, 512);
close(fil_descr);
printf("Bootsector file: %s\n" ,argv[2]);
dev=open(argv[1], O_RDWR);
assert(dev > 0);
write(dev, buf, 512);
ftab = open("filetable", O_CREAT|O_RDWR);
sprintf(buf, "{");
write(ftab, buf, 1);
for(i = 3; i < argc; i++)
{
off = off + (k * 512);
lseek(dev, off, SEEK_SET);
fil_descr=open(argv[i], O_RDONLY);
assert(fil_descr > 0);
size = 0;
while((read(fil_descr, &vbuf, 1))!=0)
{
size++;
write(dev, &vbuf, 1);
}
k = (size > 512)?2:1;
sprintf(buf, "%s-%d," ,argv[i], sect);
write(ftab, buf, strlen(buf));
printf("Input file \'%s\' written at offset %d\n", argv[i], off);
close(fil_descr);
sect = sect + k;
}
sprintf(buf,"}");
write(ftab, buf, 1);
lseek(ftab, 0, SEEK_SET);
read(ftab, buf, 512);
lseek(dev, 512, SEEK_SET);
write(dev, buf, 512);
close (dev);
close(ftab);
}

This is not a C program not working under Windows (although C is the programming language used).
What isn't woking is trying to compile a program using POSIX API functions (such as open, read, write) using a compiler targetting Win32. This includes the use of several headers that don't exist in this environment (which, if they existed, would declare functions that don't exist on the system).
You will either have to use a Unix compatibility layer (Microsoft used to sell that, not sure if they still do, also Cygwin might work), or use proper C, or use native Win32 API functions.
That said, it will also probably not work in the intended way if you switch to using the C standard library I/O funcitons or the native Win32 functions. The output "Bootsector:" suggests that you are trying something that will not work on the system drive at all, and only work with administrative privilegues on another disk.

In order to debug a problem like this, you should add some lines of code helping you to do so.
I changed the respective part of the program to
printf("Bootsector file: %s\n" ,argv[2]);
fil_descr = open(argv[2], O_RDONLY);
if (fil_descr < 0) {
perror("open");
}
printf("fil_descr: %d\n", fil_descr);
assert(fil_descr > 0);
and became aware of the fact that the 2nd command line argument must be a file name of a file to be read.
If I specify it correctly, it works fine.
The 1st file is being written to, and the remaining arguments are file names to be read as well.

Both the headers are linux specific,
#include <sys/types.h>
#include <unistd.h>

Related

Reading files to shared memory

I am reading a binary file that I want to offload directly to the Xeon Phi through Cilk and shared memory.
As we are reading fairly much data at once each time and binary data the preferred option is to use fread.
So if I make a very simple example it would go like this
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
_Cilk_shared uint8_t* _Cilk_shared buf;
int main(int argc, char **argv) {
printf("Argv is %s\n", argv[1]);
FILE* infile = fopen(argv[1], "rb");
buf = (_Cilk_shared uint8_t*) _Offload_shared_malloc(2073600);
int len = fread(buf, 1, 2073600, infile);
if(ferror(infile)) {
perror("ferror");
}
printf("Len is %d and first value of buf is %d\n", len, *buf);
return 0;
}
The example is very simplified from the real code but enough to examplify the behavior.
This code would then return
ferror: Bad address
Len is 0 and first value of buf is 0
However if we switch out the fread for a fgets (not very suitable for reading binary data, specially with the return value) things work great.
That is we switch fgets((char *) buf, 2073600, infile); and then drop the len from the print out we get
first value of buf is 46
Which fits with what we need and I can run _Offload_cilk on a function with buf as an argument and do work on it.
Is there something I am missing or is fread just not supported? I've tried to find as much info on this from both intel and other sites on the internet but I have sadly been unable to.
----EDIT----
After more research into this it seems that running fread on the shared memory with a value higher than 524287 (524287 is 19 bits exactly) fread gets the error from above. At 524287 or lower things work, and you can run as many fread as you want and read all the data.
I am utterly unable to find any reason written anywhere for this.
I don't have a PHI, so unable to see if this would make a difference -- but fread has it's own buffering, and while that may be turned of for this type of readind, then I don't see why you would go through the overhead of using fread rather than just using the lower level calls of open&read, like
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
_Cilk_shared uint8_t* _Cilk_shared buf;
int main(int argc, char **argv) {
printf("Argv is %s\n", argv[1]);
int infile = open(argv[1], O_RDONLY); // should test if open ok, but skip to make code similar to OP's
int len, pos =0, size = 2073600;
buf = (_Cilk_shared uint8_t*) _Offload_shared_malloc(size);
do {
buf[pos]=0; // force the address to be mapped to process memory before read
len = read(infile, &buf[pos], size);
if(len < 0) {
perror("error");
break;
}
pos += len; // move position forward in cases where we have no read the entire data in first read.
size -= len;
} while (size > 0);
printf("Len is %d (%d) and first value of buf is %d\n", len, pos, *buf);
return 0;
}
read & write should work with shared memory allocated without the problem you are seeing.
Can you try to insert something like this before the fread calls?
memset(buf, 0, 2073600); // after including string.h
This trick worked for me, but I don't know why (lazy allocation?).
FYI, you can also post a MIC question on this forum.

shred and remove files in linux from a C program

I want to shred some temp files produced by my C program before the files are removed.
Currently I am using
system("shred /tmp/datafile");
system("rm /tmp/datafile");
from within my program, but I think instead of calling the system function is not the best way (correct me if I am wrong..) Is there any other way I can do it? How do I shred the file from within my code itself? A library, or anything? Also, about deletion part, is this answer good?
Can I ask why you think this is not the best way to achieve this? It looks like a good solution to me, if it is genuinely necessary to destroy the file contents irretrievably.
The advantage of this way of doing it are:
the program already exists (so it's faster to develop); and
the program is already trusted.
The second is an important point. It's possible to overstate the necessity of elaborately scrubbing files (Peter Gutmann, in a remark quoted on the relevant wikipedia page, has described some uses of his method as ‘voodoo’), but that doesn't matter: in any security context, using a pre-existing tool is almost always more defensible than using something home-made.
About the only criticism I'd make of your current approach, using system(3), is that since it looks up the shred program in the PATH, it would be possible in principle for someone to play games with that and get up to mischief. But that's easily dealt with: use fork(2) and execve(2) to invoke a specific binary using its full path.
That said, if this is just a low-impact bit of tidying up, then it might be still more straightforward to simply mmap the file and quickly write zeros into it.
You can use the following code:
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define BUF_SIZE 4096
#define ABS_FILE_PATH "/tmp/aaa"
int main()
{
//get file size
struct stat stat_buf;
if (stat(ABS_FILE_PATH, &stat_buf) == -1)
return errno;
off_t fsize = stat_buf.st_size;
//get file for writing
int fd = open(ABS_FILE_PATH, O_WRONLY);
if (fd == -1)
return errno;
//fill file with 0s
void *buf = malloc(BUF_SIZE);
memset(buf, 0, BUF_SIZE);
ssize_t ret = 0;
off_t shift = 0;
while((ret = write(fd, buf,
((fsize - shift >BUF_SIZE)?
BUF_SIZE:(fsize - shift)))) > 0)
shift += ret;
close(fd);
free(buf);
if (ret == -1)
return errno;
//remove file
if (remove(ABS_FILE_PATH) == -1)
return errno;
return 0;
}

Simple encryption/decryption algorithm causing EOF

I was playing with very simple encryption/decryption algorithm like this;
#include <stdio.h>
#include <stdlib.h>
#define BUFFESIZE 1024
int main(int argc, char *argv[]) {
int keylen = 0;
char *key = argv[1];
char *buffer = NULL;
size_t buffersize = 0;
size_t nbytes = 0;
size_t nread;
int i = 0;
while(*key++ != 0) keylen++;
key = argv[1];
do {
buffersize+=BUFFESIZE;
buffer = realloc(buffer, buffersize);
nread = fread(buffer+nbytes, 1, BUFFESIZE, stdin);
nbytes+=nread;
} while (nread > 0);
for(i=0; i<nbytes; i++) {
putchar(buffer[i] ^ key[i % keylen]);
}
return 0;
}
Encyption key is the first command-line argument to the program. I expect that this should get me originial file when encrypted/decrypted with same key. However, I sometimes get only small amount of the file back if I encrypt/decrypt it. My guess is that algorithm adds EOF control character in the middle of file.
How can I get around this problem?
I compiled this using MinGW gcc 4.8.1 on windows XP. If you're interested, you can find a sample input file demonstrating the problem in the edit history of this question.
Well, your code works for me on Linux (compiled with GCC 4.8.2), even using your sample input and key. This suggests that the issue is specific to Windows — most likely, that it's caused by stdin and stdout being in text mode by default. (On Linux and other Unix-ish systems, there's usually no difference between text mode and binary mode, so such issues do not show up there.)
To fix it, you will need to set stdin and stdout to binary mode. The standard way of doing this, as of C99, would be:
freopen(NULL, "rb", stdin);
freopen(NULL, "wb", stdout);
but alas, according to the answers in the thread I linked to above, the Windows C library does not support this C99 feature, so you'll need to fall back on the non-standard _setmode() instead:
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
If you want to remain portable, you could always use some conditional code, e.g. like this (warning: not actually tested on Windows!):
#if __STDC_VERSION__ >= 199901L
#define binmode(fh, w) freopen(NULL, ((w) ? "wb" : "rb"), (fh)) /* C99 */
#elif _MSC_VER >= 1200
#include <io.h>
#include <fcntl.h>
#define binmode(fh, w) _setmode(_fileno(fh), _O_BINARY) /* MSVC 6.0+ */
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#define binmode(fh, w) /* Unix-ish, just do nothing */
#else
#error Not sure how to define binmode() on this platform
#endif
binmode(stdin, 0);
binmode(stdout, 1);
Or, of course, you could just sidestep the whole issue by opening your own input and output files (in binary mode) instead of using stdin and stdout.

C - Running an executable and retrieving output

What I am trying to do is create a program that will, while running, open examplecliprogram.exe with "--exampleparameter --exampleparameter2" as cli input, wait for examplecliprogram.exe to terminate, and then take the output and do something useful with it. I would like examplecliprogram.exe to run in the background (instead of being opened in another window) while the output from examplecliprogram.exe is displayed in the window running the overhead program.
So far I've explored options such as popen(), ShellExecute(), and CreateProcess() but I can't seem to get any of them working properly.
Primarily, I want this program to be able to run independently in a Windows environment, and compatibility with Linux would be a bonus.
edit: I have found one solution by calling system("arguments"). I don't know if this is a good solution that will transfer well to a gui, but at the very least it solves the fundamental problem.
This code runs on Windows and Unix (I tested in Visual Studio, GCC on Cygwin, and GCC on Mac OS X).
I had to use a macro to define popen depending on the platform, because on Windows, the function is _popen, while on other platforms the function name is popen (note the underscore in the former).
#include <stdlib.h>
#include <stdio.h>
/* Change to whichever program you want */
//#define PROGRAM "program.exe --param1 --param2"
#define PROGRAM "dir"
#define CHUNK_LEN 1024
#ifdef _WIN32
#define popen _popen
#define pclose _pclose
#endif
int main(int argc, char **argv) {
/* Ensure that output of command does interfere with stdout */
fflush(stdin);
FILE *cmd_file = (FILE *) popen(PROGRAM, "r");
if (!cmd_file) {
printf("Error calling popen\n");
}
char *buf = (char *) malloc(CHUNK_LEN);
long cmd_output_len = 0;
int bytes_read = 0;
do {
bytes_read = fread(buf + cmd_output_len, sizeof(char), CHUNK_LEN, cmd_file);
cmd_output_len += bytes_read;
buf = (char *) realloc(buf, cmd_output_len + CHUNK_LEN);
} while (bytes_read == CHUNK_LEN);
/* Nul terminate string */
*((char *) buf + cmd_output_len) = '\0';
/* Close file pointer */
pclose(cmd_file);
/* Do stuff with buffer */
printf("%s\n", buf);
/* Free buffer */
free(buf);
return 0;
}
You may want to have a look to this Microsoft example code. It was useful to me.
http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx
I used CreateProcess, unfortunately I can't recommend you anything other than 'carefull reading of msdn' and 'starting from simple and progress to complex'.
As for the portability - if you havent need to use some cross-platform toolkit until now, i wouldnt recommend you to start to use one just because of this. I would recommend you to write some 'start process' wrapper and implement it on each platform by its native way.
The cleanest and most portable way of doing this is to use GLib's g_spawn_sync().
You can find the docs online.
gchar * std_out = NULL;
gchar * std_err = NULL;
gint exit_stat = 0;
const char *argv[] = {"--foo", "123", "--bar", "22323", NULL};
if(!g_spawn_sync (NULL, argv, NULL, NULL, NULL, NULL, &std_out, &std_err, &exit_stat, NULL)){
fprintf(stderr, "Failed to spawn!\n");
};
/* std_out and std_err should now point to the respective output.*/

Windows C SHA256 Invalid Generation Issue

Hey there. I'm having a very strange problem with creating sha256 hashes. I made a simple C console program that takes a file path as an argument and uses the standalone sha256 code that can be found here. I compiled the program using MinGW 5.1.6 on Windows 7 x64.
When testing the program on a file, the resultant hash is wrong. I made sure of this by using md5deep on the file, and then by using sha256sum on the file under Linux.
I also verified it was not the code by compiling and running the same code on my Linux box with the same file; the hash it produced was identical to the ones produced by md5deep and sha256sum.
I also adapted Aaron Gifford's sha256 implementation into a different version of my simple program and performed the test again on both Windows and Linux and ended up with the same result.
Could it be possible that the issue is being caused by compiler flags that have not been switched on?
My knowledge of C isn't amazing and my knowledge of compiler options is even worse, so any help would be kindly appreciated.
The code for the simple program is below:
#include <stdio.h>
#include "sha256.h"
#define BUFLEN 16384
int main(int argc, char *argv[]) {
sha256_context ctx256;
sha256_starts(&ctx256);
int kl, l, fd;
unsigned char buf[BUFLEN];
FILE *file = (FILE*) 0;
char *filepath;
fd = fileno(stdin);
filepath = argv[1];
file = fopen(filepath, "r");
fd = fileno(file);
while ((l = read(fd, buf, BUFLEN)) > 0) {
kl += l;
sha256_update(&ctx256, buf, l);
}
fclose(file);
uint8 sha256sum[32];
sha256_finish(&ctx256, sha256sum);
int i;
for (i = 0; i < 32; i++) {
printf("%02x", sha256sum[i]);
}
printf("\n");
return 0;
}
Binary mode gets ignored on Linux, but it applies in Windows. For reference on what it does, see http://msdn.microsoft.com/en-us/library/yeby3zcb%28VS.71%29.aspx. In short, \r\n gets translated to \n in non-binary mode.

Resources