[gull] Tronquer des fichiers log
Marc Mongenet
marc at mongenet.ch
Wed Jan 5 02:22:08 CET 2011
Le 4 janvier 2011 07:57, Frédéric Benninger <benninger at sunrise.ch> a écrit :
> Car il s’agit bien de garder une certaine quantité de données (ko ou
> nb lignes) à partir de la fin d’un fichier en s’arrêtant à un saut de
> ligne.
Oui bien sûr, j'étais à coté de la plaque.
Du coup le programme en C devient plus compliqué...
J'ai fait ça:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void usage(const char *argv0)
{
fprintf(stderr, "%s lines files...\n", argv0);
exit(1);
}
int get_prev_char(int fd, char *pc)
{
if (lseek(fd, -1, SEEK_CUR) == -1) return -1;
if (read(fd, pc, 1) == -1) return -1;
if (lseek(fd, -1, SEEK_CUR) == -1) return -1;
return 0;
}
int copy_end_to_start(int fd, off_t read_pos)
{
off_t write_pos = 0;
char c;
ssize_t read_ret;
while ((read_ret = read(fd, &c, 1)) == 1) {
++read_pos;
if (lseek(fd, write_pos, SEEK_SET) == -1) return -1;
if (write(fd, &c, 1) != 1) return -1;
++write_pos;
if (lseek(fd, read_pos, SEEK_SET) == -1) return -1;
}
if (read_ret != 0) return -1;
return 0;
}
void shrink(const char *fn, long lines)
{
const int fd = open(fn, O_RDWR);
if (fd == -1) goto error;
const off_t fsize = lseek(fd, 0, SEEK_END);
if (fsize == -1) goto error;
off_t fpos = fsize;
long count_lines = 0;
while (fpos > 0 && count_lines <= lines) {
char c;
if (get_prev_char(fd, &c) == -1) goto error;
--fpos;
if (c == '\n' || count_lines == 0) ++count_lines;
}
if (fpos > 0) {
if (lseek(fd, 1, SEEK_CUR) == -1) goto error;
if (copy_end_to_start(fd, fpos + 1) == -1) goto error;
if (ftruncate(fd, fsize - fpos - 1) == -1) goto error;
}
close(fd);
return;
error:
perror(fn);
if (fd != -1) close(fd);
}
int main(int argc, char **argv)
{
if (argc < 3) usage(argv[0]);
char *endptr;
const long lines = strtol(argv[1], &endptr, 10);
if (*argv[1] == '\0' || *endptr != '\0' || lines < 0)
usage(argv[0]);
for (int i = 2; i < argc; ++i)
shrink(argv[i], lines);
return 0;
}
More information about the gull
mailing list