I have this code and canĀ“t get it properly to work. I want to write the String Output into a file.
static void wr_message_user_info_login(wi_p7_message_t *message) {
wi_date_t *date;
wi_string_t *string, *interval;
wi_p7_uint32_t uid, build, bits;
wr_printf_block(WI_STR("Login: %#"),
wi_p7_message_string_for_name(message, WI_STR("wired.user.login")));
char *filename = "/.wirebot/wirebot.login";
char *home_dir = getenv("HOME");
char *filepath = malloc(strlen(home_dir) + strlen(filename) + 1);
sprintf(filepath, "%s%s", home_dir, filename);
FILE *fp;
fp = fopen(filepath, "w");
if (fp == NULL)
{
}
else
{
fputs((WI_STR("Login: %#")), fp);
);
fclose(fp);
}
"Login: %#" should be writed to file. Echoing is working fine.
You provided a snippet of code with a lot of stuff missing. If you strip the stuff you haven't told us about it seems to work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void wr_message_user_info_login() {
const char *filename = "/.wirebot/wirebot.login";
const char *home_dir = getenv("HOME");
char *filepath = malloc(strlen(home_dir) + strlen(filename) + 1);
if(!filepath) {
printf("malloc failed\n");
return;
}
sprintf(filepath, "%s%s", home_dir, filename);
FILE *fp = fopen(filepath, "w");
if (!fp) {
printf("fopen failed\n");
free(filepath);
return;
}
free(filepath);
fputs("Login: %#", fp);
fclose(fp);
}
int main() {
wr_message_user_info_login();
}
and example run:
$ mkdir ~/.wirebot && ./a.out && cat ~/.wirebot/wirebot.login
Login: %#
Maybe the directory ~/.wirebot doesn't exist on your host?
Related
I'm using miniz to create a .zip file in C, on Windows.
I used the doc to produce my code and it works. I can create an archive with the files I want, ONLY if I give relative path to the zip function.
I don't get why the "file_name" variable must be something like "../test/file.txt" and not "C:/../test/file.txt".
if (!(status = mz_zip_add_mem_to_archive_file_in_place(archive, file_name, data, strlen(data) + 1, s_pComment,
(uint16) strlen(s_pComment), MZ_BEST_COMPRESSION)))
return (merror("add file to archive failed !!"));
Before this function, I open my file, get the data inside and call the zip_function with it.
if (!(src = fopen(file_name, "r")))
return (merror("can't open this file"));
char *line = NULL;
char *data= NULL;
size_t n = 0;
getline(&line, &n, src);
data= strdup(line);
while (getline(&line, &n, src) != -1){
data = realloc(save, sizeof(char) * (strlen(data) + strlen(line)) + 1);
data = strcat(data, line);
}
fopen(src);
So I call the zip function with the archive name, the file name (with the absolute path) and the datas inside it (in char * format).
This is the "full" code : the function init_zip is the first function called by my program. The arg parameter is the archive name I want to be create(it can be an absolute path and works) and the args parameter are the names of the differents files I want to add to the archive file (relative path works but not absolute).
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint;
static const char *s_pComment = "";
static int isDirectory(const char *path) {
struct stat statbuf;
if (stat(path, &statbuf) != 0)
return 0;
return S_ISDIR(statbuf.st_mode);
}
int get_data(const char *archive, const char *file)
{
FILE *src;
if (!isDirectory(file)) {
if (!(src = fopen(file, "r")))
return (merror("can't open this file"));
char *line = NULL;
char *save = NULL;
size_t n = 0;
getline(&line, &n, src);
save = strdup(line);
while (getline(&line, &n, src) != -1) {
save = realloc(save, sizeof(char) * (strlen(save) + strlen(line)) + 1);
save = strcat(save, line);
}
printf("compressing %s ..\n", file);
if (m_compress(archive, file, save))
return (merror("compress function failed"));
printf(("\tOK.\n"));
fclose(src);
}
else
{
DIR *dir;
struct dirent *entry;
char *new_file;
if (!(dir = opendir(file)))
return (merror("opendir failed: ", "wrong directory path in init_zip.get_data command : ", file, NULL));
while ((entry = readdir(dir)) != NULL)
{
if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
new_file = add_path(file, entry->d_name);
get_data(archive, new_file);
}
}
if (new_file)
free(new_file);
closedir(dir);
}
}
int init_zip(const char *arg, const char **args)
{
printf("\nZIP cmd:\n >");
remove(arg);
for (int counter = 0; args[counter]; ++counter)
{
get_data(arg, args[counter]);
}
printf("All the files are added to %s archive file.\n", arg);
return (0);
}
int m_compress(const char *archive, const char *file_name, const char *data)
{
mz_bool status;
if (data)
if (!(status = mz_zip_add_mem_to_archive_file_in_place(archive, file_name, data, strlen(data) + 1, s_pComment,
(uint16) strlen(s_pComment), MZ_BEST_COMPRESSION)))
return (merror("add file to archive failed !!"));
else
if (!(status = mz_zip_add_mem_to_archive_file_in_place(archive, file_name, NULL, 0, "no comment", (uint16)strlen("no comment"), MZ_BEST_COMPRESSION)))
return (merror("add directory to archive failed !!"));
return (0);
}
This is the add_path() function used in get_data():
char *add_path(const char *str1, const char *str2)
{
char *path;
path = malloc(sizeof(char) * (strlen(str1) + 1 + strlen(str2) + 1));
path = strcpy(path, str1);
path = strcat(path, "/");
path = strcat(path, str2);
return (path);
}
Anyone knows something about it?
If nothing helps, then you should lookup the sources. Following the code in miniz on Github, file miniz_zip.c line 4297 I see:
mz_bool mz_zip_add_mem_to_archive_file_in_place(...
which calls function mz_zip_writer_validate_archive_name to check the second filename provided that it cannot start with a drive letter (line 3069) and if so
returns FALSE with error set to MZ_ZIP_INVALID_FILENAME.
As to why this second filename may not be an absolute path, I don't know. If it is important to you, you could get the code from Github and adapt it.
I have an elf file that called example. I wrote following code which it's read the content of the example file in the binary mode and then I wanted to save their content in another file called example.binary. But when I run the following program it shows me a segmentation fault. What's wrong with this program? I can't find out my mistake.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// typedef macro
typedef char* __string;
//Function prototypes
void readFileToMachine(__string arg_path);
int main(int argc, char *argv[]) {
__string pathBinaryFile;
if(argc != 2){
printf("Usage : ./program file.\n");
exit(1);
}
pathBinaryFile = argv[1];
readFileToMachine(pathBinaryFile);
return EXIT_SUCCESS;
}
void readFileToMachine(__string arg_path){
int ch;
__string pathInputFile = arg_path;
__string pathOutputFile = strcat(pathInputFile, ".binary");
FILE *inputFile = fopen(pathInputFile, "rb");
FILE *outputFile = fopen(pathOutputFile, "wb");
ch = getc(inputFile);
while (ch != EOF){
fprintf(outputFile, "%x" , ch);
ch = getc(inputFile);
}
fclose(inputFile);
fclose(outputFile);
}
You have no room to concatenate extention to path so you have to create space for that.
One solution could be:
char ext[] = ".binary";
pathOutputFile = strdup(arg_path);
if (pathOutputFile != NULL)
{
pathOutputFile = realloc(pathOutputFile, strlen(arg_path) + sizeof(ext));
if (pathOutputFile != NULL)
{
pathOutputFile = strcat(pathInputFile, ext);
// YOUR STUFF
}
free(pathOutputFile);
}
Side note: typedef a pointer is not a good idea...
change your typedef to typedef char* __charptr
void rw_binaryfile(__charptr arg_path){
FILE *inputFile;
FILE *outputFile;
__charptr extension = ".binary";
__charptr pathOutputFile = strdup(arg_path);
if (pathOutputFile != NULL){
pathOutputFile = realloc(pathOutputFile, strlen(arg_path) + sizeof(extension));
if (pathOutputFile != NULL){
pathOutputFile = strcat(pathOutputFile, ".binary");
inputFile = fopen(arg_path, "rb");
outputFile = fopen(pathOutputFile, "wb");
write_file(inputFile, outputFile);
}
}
}
void write_file(FILE *read, FILE *write){
int ch;
ch = getc(read);
while (ch != EOF){
fprintf(write, "%x" , ch);
ch = getc(read);
}
}
I'm new to C programming. I made a very short program to merge all the files in a folder.
The program runs and produces the right output, but after execution it hangs and I have to manually kill it.
Any ideas why?
The important functions here are scandir and append_to_file
/*
MERGE: Merges text files. Gives the ability to merge a list of files or all files in a
directory with specified extension.
*/
#include <stdio.h>
#include <dirent.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
/* Function prototypes */
int append_to_file(const char *filename, const char *outfilename); // Appends the contents of filename to outfilename
int scandir(char dirname[], char const *ext, char outfile[]); // Scans a directory for files of a specific extension and merges them
bool has_extension(char const *name, char const *ext);
void usage(); // Prints out usage information (help) to the console
void path_combine(char *dest, const char *path1, const char *path2); // Combines a directory name and filename to a single filepath
int main(int argc, char *argv[])
{
int i, // Counters
nfiles; // Number of files merged
if (argc == 4)
{
nfiles = scandir(argv[1], argv[2], argv[3]);
printf("Merged %s files\n", nfiles);
return 0;
}
else
{
printf("Wrong input, quitting");
return 1;
}
}
int append_to_file(const char *filename, const char *outfilename)
{
FILE *infile, *outfile;
char ch;
infile = fopen(filename, "r");
outfile = fopen(outfilename, "a");
if (infile == NULL)
{
printf("Input file is empty, skipping...\n");
return 1;
}
while ((ch = fgetc(infile)) != EOF)
fputc(ch, outfile);
fclose(infile);
fclose(outfile);
return 0;
}
int scandir(char dirname[], char const *ext, char outfile[])
/* Scans a directory and merges all files of given extension */
{
DIR *d = NULL;
struct dirent *dir = NULL;
char filepath[strlen(dirname) + 255];
int i = 0;
d = opendir(dirname);
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (has_extension(dir->d_name, ext))
{
path_combine(filepath, dirname, dir->d_name);
printf("%s\n", filepath);
append_to_file(filepath, outfile);
i++;
}
}
closedir(d);
}
return i;
}
bool has_extension(char const *name, char const *ext)
{
size_t len = strlen(name);
return len > 4 && strcmp(name+len-4, ext) == 0;
}
void path_combine(char *dest, const char *path1, const char *path2)
{
const char *last_char = path1;
int append_sep = 0;
char sep[] = "/";
#ifdef WIN32
sep[0] = '\\';
#endif
/* Find the last character in the first path*/
while(*last_char != '\0')
last_char++;
/* If the last character is not a seperator, we must add it*/
if (strcmp(last_char, sep) !=0)
{
append_sep = 1;
}
strcpy(dest, path1);
if (append_sep)
strcat(dest, sep);
strcat(dest, path2);
}
void usage()
{
printf("\t=================\n");
printf("\t MERGE\n");
printf("\t=================\n");
printf("Merge two or more text files\n");
printf("Usage:\n");
printf("\tCall merge with a directory name and desired extension:\n");
printf("\tmerge DIRNAME .csv OUTPUTFILE\n\n");
};
As the compiler warned you (if you compile with gcc -Wall -g), the following line:
printf("Merged %s files\n", nfiles);
is wrong, since nfiles is an int. You probably want
printf("Merged %d files\n", nfiles);
Read about undefined behavior. You've got one. Read also carefully the documentation of every function you are using, starting with printf(3) & fopen(3) & perror(3) & exit(3). Don't forget to handle failure, e.g:
FILE *infile, *outfile;
char ch;
infile = fopen(filename, "r");
outfile = fopen(outfilename, "a");
if (infile == NULL) {
printf("failed to open %s (%s), skipping...\n",
filename, strerror(errno));
return 1;
}
if (outfile == NULL) {
perror(outfilename);
exit(EXIT_FAILURE);
}
Learn how to use your debugger (gdb). If on Linux, use also strace(1) and valgrind.
Ah.
I thought I was using the debugger, by specifying -g when compiling:
gcc main.c -g -o main.exe
But it was still hanging.
If I included the flags -Wall and -Werror it soon told me that I had a string formatting error.
the line printf("Merged %s files\n", nfiles) needed to be changed to printf("Merged %d files\n", nfiles).
Compiling with -Wall and -Werror soon pointed out this mistake.
I'm trying to crypt a file using ceasarshift, a new file called .enc is being created but it's empty.
Here's my code :
#include <stdio.h>
#include <string.h>
char* getFileExtension(const char*);
int main(int argc, char *argv[])
{
const int shift = (int)argv[1];
int byte;
const char *fileName = (char*)argv[2];
char *fileExtension = getFileExtension(fileName);
char *newFileName = (char*)fileName;
FILE *f_in;
FILE *f_out;
f_in = fopen(fileName, "r");
if (strcmp(fileExtension, "enc") == 0)
{
// We want to decrypt the file
strcat(newFileName, ".dec");
f_out = fopen(newFileName, "w");
while ((byte = fgetc(f_in) != EOF))
{
fputc(byte - shift, f_out);
}
}
else
{
// We want to encrypt the file
strcat(newFileName, ".enc");
f_out = fopen(newFileName, "w");
while ((byte = fgetc(f_in) != EOF))
{
fputc(byte + shift, f_out);
}
}
fclose(f_in);
fclose(f_out);
return 0;
}
char* getFileExtension(const char *fileName)
{
char *extension;
int foundExtension = 0;
while (*fileName)
{
if (foundExtension == 1)
{
*extension++ = *fileName++;
}
if (*fileName == '.')
{
foundExtension = 1;
}
fileName++;
}
return extension;
}
I've made a txt file named CryptoFile which contains the following text :
This is a crypto test file !
This is the parameters I sent in the console when running the exe :
FileCaesarShift.exe 15 CryptoFile
So the shift is 15, the file to encrypt/decrypt is called "CryptoFile"
although a file called CryptoFile.enc is being created it's simply empty.
Can someone tell me what I did wrong ?
Ok I've found out that I need to pass CryptoFile.txt including the ".txt" but I wish to remove it from the name of the new files that will be created so instead of creating CryptoFile.txt.enc I want only CryptoFile.enc so I made a removeExtension function but my program crashes , here's the new code :
#include <stdio.h>
#include <string.h>
char* getFileExtension(const char*);
void removeFileExtension(char*);
int main(int argc, char *argv[])
{
const int shift = (int)argv[1];
int byte;
const char *fileName = (char*)argv[2];
char *fileExtension = getFileExtension(fileName);
char *newFileName = (char*)fileName;
removeFileExtension(newFileName);
printf("newfilename value is %s", *newFileName);
FILE *f_in;
FILE *f_out;
f_in = fopen(fileName, "r");
if (strcmp(fileExtension, "enc") == 0)
{
// We want to decrypt the file
strcat(newFileName, ".dec");
f_out = fopen(newFileName, "w");
while ((byte = fgetc(f_in)) != EOF)
{
fputc(byte - shift, f_out);
}
}
else
{
// We want to encrypt the file
strcat(newFileName, ".enc");
f_out = fopen(newFileName, "w");
while ((byte = fgetc(f_in)) != EOF)
{
printf("byte is %d\n", byte);
fputc(byte + shift, f_out);
}
}
fclose(f_in);
fclose(f_out);
return 0;
}
char* getFileExtension(const char *fileName)
{
char *extension;
int foundExtension = 0;
while (*fileName)
{
if (foundExtension == 1)
{
*extension++ = *fileName++;
}
if (*fileName == '.')
{
foundExtension = 1;
}
fileName++;
}
return extension;
}
void removeFileExtension(char *fileName)
{
while (*fileName)
{
if (*fileName == '.')
{
*fileName == '\0';
break;
}
fileName++;
}
}
LATEST EDIT :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void copyFileExtension(char*, char*);
int getFileNameLengthWithoutExtension(char*);
int getFileExtensionLength(char*);
void copyFileNameWithoutExtension(char*, char*);
int main(int argc, char *argv[])
{
int shift = atoi(argv[1]);
int byte;
char *fileName = (char*)argv[2];
char *fileExtension = malloc(getFileExtensionLength(fileName) + 1);
copyFileExtension(fileExtension, fileName);
char *newFileName = malloc(getFileNameLengthWithoutExtension(fileName) + 5);
copyFileNameWithoutExtension(newFileName, fileName);
FILE *f_in;
FILE *f_out;
f_in = fopen(fileName, "r");
if (strcmp(fileExtension, "enc") == 0)
{
// We want to decrypt the file
puts("dec");
strcat(newFileName, ".dec");
f_out = fopen(newFileName, "w");
while ((byte = fgetc(f_in)) != EOF)
{
fputc(byte - shift, f_out);
}
}
else
{
puts("enc");
// We want to encrypt the file
strcat(newFileName, ".enc");
f_out = fopen(newFileName, "w");
while ((byte = fgetc(f_in)) != EOF)
{
fputc(byte + shift, f_out);
}
}
fclose(f_in);
fclose(f_out);
return 0;
}
void copyFileExtension(char *fileExtension, char *fileName)
{
char *token = strtok(fileName, ".");
token = strtok(NULL, ".");
strcpy(fileExtension, token);
}
int getFileNameLengthWithoutExtension(char *fileName)
{
if (*fileName && *fileName != '.')
{
return 1 + getFileNameLengthWithoutExtension(++fileName);
}
return 0;
}
int getFileExtensionLength(char *fileName)
{
int foundExt = 0;
int len = 0;
while(*fileName)
{
if (foundExt == 1)
{
len++;
}
if (*fileName == '.')
{
foundExt = 1;
}
fileName++;
}
printf("ext len is %d\n", len);
return len;
}
void copyFileNameWithoutExtension(char* dest, char *source)
{
char *fileNameWithoutExtension = strtok(source, ".");
strcpy(dest, fileNameWithoutExtension);
}
Here are a few things one can notice at a quick glance:
const int shift = (int)argv[1] does not convert the input argument to the integer value 15. Rather it casts the char* pointer in argv[1] (that is the address) into an int and assigns that (typically quite large) value to shift. To actually convert the input argument into an int consider using atoi.
you are not allocating memory for newFileName, and later writing possibly past the allocated length of the "constant" input argv[2] which newFileName points to (which results in undefined behavior).
Assuming the program doesn't crash before that, the operator precedence rule between = and != makes your while loop arguments equivalent to byte = (fgetc(f_in) != EOF). So before you reach EOF, byte == 1. If you had a shift of 15 you wind up creating a file full of unreadable control characters (ascii character 16). Given the unpredictable shift from the first bullet, who knows what is actually going to be written to file.
Though these are probably not your specific errors, the following could also cause problem:
You are also not checking whether the files were opened successfully before using them
Have you consider what would happen for letters that are near the end of the valid characters?
Someone ask me to help them extract their pictures from a Web Shots image collection file (.WBC). I tried XnView but it did not work. How can I do this in C?
From Mike:
I hacked together some code to do the job. Here it is. It's not production quality code, so if you do not understand it then do not run it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void save_image(const char* filename, FILE* in_fp)
{
char buf[4096];
size_t read;
FILE *fp;
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "cannot open file.");
exit(1);
}
do {
read = fread(buf,1,sizeof(buf),in_fp);
fwrite(buf, 1, read, fp);
} while (read);
fclose(fp);
}
int main(int argc, char* argv[])
{
char buf[4096];
unsigned int read, read_tot = 0;
FILE *fp;
int image_count = 1;
char filename[255];
unsigned int i;
char pattern[] = "JFIF";
int pi = 0;
long int curpos;
char pad[50];
char src_filename[] =
"C:\\Documents and Settings\\mikeking\\Desktop\\WBC\\"
"Custom - CATHYS WEDDING.wbc";
char des_directory[] = "C:\\Documents and Settings\\mikeking\\Desktop\\F\\";
fp = fopen(src_filename, "rb");
if (!fp) {
fprintf(stderr, "cannot open file.");
exit(1);
}
do {
read = fread(buf,1,sizeof(buf),fp);
for(i=0; i<read; i++){
if (buf[i] == pattern[pi]) {
pi++;
if (pi == sizeof(pattern)) {
strcpy(filename, des_directory);
itoa(image_count, pad, 10);
image_count++;
strcat(filename, pad);
strcat(filename, ".jpg");
curpos = ftell(fp);
fseek(fp,read_tot+i-10,SEEK_SET);
save_image(filename,fp);
fseek(fp,curpos,SEEK_SET);
}
} else {
pi = 0;
}
}
read_tot += read;
} while (read);
fclose(fp);
return 0;
}