I would like to add logs at the end of a file for each event, and create a new one when its size up to 255 Mo.
For example, the current file could be /var/log/foo.2:
/var/log/foo.0.log (full log file)
/var/log/foo.1.log (full log file)
/var/log/foo.2.log
Have you got an idea of C source to do so?
Thank you
When opening the file with
File *fopen(const char *filename, const char *mode);
choose "a" as mode. Which will open or create a text file for writing at the end of file.
Basic c file code: http://c-programming.suite101.com/article.cfm/c_tutorial_file_handling_commands
If you just want to have the functionality, look at log4c.
If you want to know how that works, you can look at its code as well.
If you need specially tailored code for your application...
Basically you need to use fopen with the "a" option, where a stands for append.
To determine size of a file, use ftell or another platform specific function because there is no file size information method in the C standard as far as I can remember. Or you go the long way and just read all the bytes from the file and count them...
Related
I am developing a command line application in C (linux environment) to edit a particular file format. This file format is a plain XML file, which is compressed, then encrypted, then cryptographically signed.
I'd like to offer an option to the user to edit this kind of file in an easy way, without the hassle of manualy extracting the file, editing it, and then compressing, encrypting and signing it.
Ideally, when called, my application should do the following:
Open the encrypted/compressed file and extract it to a temporary location (like /tmp)
Call an external text editor like nano or sublime-text or gedit depending on which is installed and maybe the user preferences. Wait until the user have edited the file and closed the text editor.
Read the modified temporary file and encrypt/compress it, replacing the old encrypted/compressed file
How can I achieve point no. 2?
I thought about calling nano with system() and waiting for it to return, or placing an inotify() on the temp file to know when it is modified by the graphical text editor.
Which solution is better?
How can i call the default text editor of the user?
Anything that can be done in a better way?
First, consider not writing an actual application or wrapper yourself, which calls another editor, but rather writing some kind of plugin for some existing editor which is flexible enough to support additional formats and passing its input through decompression.
That's not the only solution, of course, but it might be easier for you.
With your particular approach, you could:
Use the EDITOR and/or VISUAL command-line variables (as also pointed out by #KamilCuk) to determine which editor to use.
Run the editor as a child process so that you know when it ends execution, rather than having to otherwise communicate with it. Being notified of changes to the file, or even to its opening or closing, is not good enough, since the editor may make changes multiple files, and some editors don't even keep the file open while you work on it in them.
Remember to handle the cases of the editor failing to come up; or hanging; or you getting some notification to stop waiting for the editor; etc.
Call an external text editor like nano or sublime-text or gedit depending on which is installed and maybe the user preferences. Wait until the user have edited the file and closed the text editor.
Interesting question. One way to open the xml file with the user's default editor is using the xdg-open, but it doesn't give the pid of the application, in which user will edit the file.
You can use xdg-mime query default application/xml to find out the .desktop file of the default editor, but then you have to parse this file to figure out the executable path of the program - this is exactly how xdg-open actually works, in the search_desktop_file() function the line starting with Exec= entry is simply extracted from the *.desktop to call the editor executable and pass the target file as argument... What I am trying to say, is, after you find the editor executable, you can start it, and wait until it's closed, and then check if the file content has been changed. Well, this looks like a lot of unnecessary work...
Instead, you can try a fixed well-known editor, such as gedit, to achieve the desired workflow. You can also provide user a way (i.e. a prompt or config file) to set a default xml editor, i.e. /usr/bin/sublime_text, which then can be used in your programm on next run.
However, the key is here to open an editor that blocks the calling process, until user closes the editor. After the editor is closed, you can simply check if the file has been changed and if so, perform further operations.
To find out, if the file contents have been modified, you can use the stat system call to get the inode change time of the file, before you open the file, and then compare the timestamp value with the current one once it is closed.
i.e.:
stat -c %Z filename
Output: 1558650334
Wrapping up:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void execute_command(char* cmd, char* result) {
FILE *fp;
fp = popen(cmd, "r");
fscanf (fp, "%s" , result);
}
int get_changetime(char* filename) {
char cmd[4096];
char output[10];
sprintf(cmd, "stat -c %%Z %s", filename);
execute_command(cmd, output);
return atoi(output);
}
int main() {
char cmd[4096];
char* filename = "path/to/xml-file.xml";
uint ctime = get_changetime(filename);
sprintf(cmd, "gedit %s", filename);
execute_command(cmd, NULL);
if (ctime != get_changetime(filename)) {
printf("file modified!");
// do your work here...
}
return 0;
}
I'm trying to move some .csv files from a directory "NotImported" to another directory "Imported" after each file fclose().
Unfortunately I couldn't find a way!
I would say,
rename(const char *oldpath, const char *newpath);
all explained here (it's long to read but you'll learn a lot each time): man page of rename
I am creating a application, input to which is a C file having an array ( which is created with bin2C.exe ) , the code segment of the C file is:-
unsigned int MyArray[] = { 0x00000001,0x00000002,0x00000005 ...};
now I need to read this array as a text file and story its value in an int array. Then I need to modify that array and put it back to text file so that the final output would look like:-
unsigned int MyArray[] = { 0x39481212,0x33943121,0x3941212 ...};
Please let me know how can I do this in C/VisualC++ as my application is in VC++ with MFC?
Regards,
Vikas
input
open the file (fopen) in text mode and read the lines (fgets and sscanf)
store array
you cannot have an array with unspecified size. You must either use a size limit and leave some elements unused, or use malloc and friends and manage storage for the array manually
modify
use +, -, * and other operators along with sqrt, abs, sin and other functions available in the Standard Library to massage the data (you can create some functions of your own too)
put it back
It's better to write to a new file and if everything went ok, delete the old file and rename the new one ... so open the new file (fopen with "w" for mode parameter) at the beginning when opening the input; if the input is not the array line write (fputs) it back directly, otherwise write the 'massaged' line; read and write all the other lines.
(C++?) with MFC
The above is for C. It might work for C++ with or without MFC
Regards
Have fun!
I think the best way was to read and use fprintf/sprintf functions to get and put the data as int from file.
I need to add a string before the 45th byte in an existing file. I tried using fseek as shown below.
int main()
{
FILE *fp;
char str[] = "test";
fp = fopen(FILEPATH,"a");
fseek(fp,-45, SEEK_END);
fprintf(fp,"%s",str);
fclose(fp);
return(0);
}
I expected that this code will add "test" before the 45th char from EOF, instead, it just appends "test" to the EOF.
Please help me to find the solution.
This is continuation of my previous question
Append item to a file before last line in c
Open it with mode r+ (if it already exists) or a+ (if it doesn't exist and you want to create it). Since you're seeking to 45 bytes before the end of file, I'm assuming it already exists.
fp = fopen(FILEPATH,"r+");
The rest of your code is fine. Also note that this will not insert the text, but will overwrite whatever is currently at that position in the file.
ie, if your file looks like this:
xxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxx
Then after running this code, it will look like this:
xxxxxxxtestxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxx
If you really want to insert and not overwrite, then you need to read all the text from SEEK_END-45 to EOF into memory, write test and then write the text back
Don't open it as append (a) if you plan to write at arbitrary positions; it will force all writes to the end of the file. You can use r+ to read or write anywhere.
To avoid platform-specific configurations, always explicitely indicate the binary or text mode in your fopen() call.
This will save you hours of desperations if you port your code one day.
Assume I have a file pointer FILE* myfile. Is there a way to retrieve the name of the file where myfile is reading from or writing to?
Not in any CRT implementation that I've ever seen. It is useless info, you already have to supply the file name to get a FILE*. You could probably dig an operating system handle out of the FILE structure although you might need to hop through a file descriptor table. Your next problem is then the operating system support you'd need to map a file handle back to a file name. That should be difficult too.
I found a nice example that uses an overwritten struct MyFile:
How to get filename from a FILE*