My Blog

fpurge() hack — Koszek trick #1

PDF ·

A friend of mine asked me once:

How to recover text formatted by printf(), but do not spit it output to the console?

Right now I don’t exactly remember why fprintf() couldn’t be used, but I remember this was in the environment where fprintf() (or all?) changes couldn’t be applied.

This is a technique I was came up with. Please note: this is HUGE hack and it is not proven to work on your system. It is based on the fact data from printf function family is first written to the buffer buf, and until it’s internally flushed, it won’t be printed. Lack of flush is implicitly expected due to the large buffer size, and buffering set by setbuf. Once we generate enough data in the buf buffer through fprintf calls, we copy the data to text buffer, and discard buf buffer. Discarding happens via fprune and its associated file descriptor, for which buffer has been used for.

It used to work on FreeBSD and GNU/Linux, but PLEASE don’t make your code depend on that. It’s a hack. Here it is:


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SZ 1024*1024

/*
 * This is Koszek's trick to write formated data to the FILE structure
 * with an underlying buffer, but without flushing it to the backing
 * descriptor. Later on, once a buffer is filled, I print it to get a
 * proof and clear it.
 */
int
main(int argc, char **argv)
{
 char buf[SZ];
 char text[SZ];
 FILE *fp;

 (void)argc;
 (void)argv;

 memset(buf, 0, sizeof(buf));

 fp = fopen("FILE.txt", "a+");
 assert(fp != NULL);
 fflush(fp);
 setbuf(fp, buf);

 fprintf(fp, "Nie wiem co napisaæ\n");
 fprintf(fp, "Nie wiem co tutaj wklepaæ\n");
 fprintf(fp, "To ma tylko wyczy¶ciæ bufor\n");

 memcpy(text, buf, sizeof(text));

 fpurge(fp);
 setbuf(fp, NULL);

 printf("Text: '%s'\n", text);

 fflush(fp);
 fclose(fp);
 return (EXIT_SUCCESS);
}
#softwareengineering