obtener posicion en un file descriptor??
Daniel Serpell
dserpell en gmail.com
Sab Ene 31 21:44:58 CLST 2009
Hola!
El Sat, Jan 31, 2009 at 07:26:51PM -0300, Rodrigo Ahumada escribio:
> Daniel Serpell escribió:
>>
>> Lo que yo hago normalmente es utilizar 'dd' en medio, de la siguiente
>> manera:
>>
>> cat /mi/archivo/grande | dd | algoQueHacer
>>
>> Luego, le puedes mandar una señal SIGUSR1 al dd para que muestre el estado
>> de la copia (por ejemplo, con "kill -USR1 $(pgrep dd)".)
>
> No se si será posible: si el programa que se quiere monitorear usa
> fwrite o write para escribir, se tiene el código fuente como para estar
> seguro de eso, se podría hacer una .so con la función fwrite o write
> reescrita para que tire cada cierto avance, la posicion en el archivo, a
> un archivo en /tmp..., y luego lanzar el programa haciendo que cargue el
> .so antes que las libc....
Oh, claro que es posible, mira este ejemplo, compila con
gcc -shared -fPIC -O2 -Wall -o dwrite.so dwrite.c
Y luego lo usas como:
LD_PRELOAD=./dwrite.so:/lib/libdl.so.2 cat /some/big/file > /dev/null
El problema es que no resuelve la pregunta original, ya que el parche de
biblioteca se debe aplicar *antes* de iniciar el programa.
Claro, uno podría mediante GDB inyectar código adicional en tiempo de
ejecución, pero eso es bastante complejo.
Daniel.
//---------- dwrite.c -----------
#define _GNU_SOURCE
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>
#include <stdio.h>
ssize_t write(int fd, const void *buf, size_t count)
{
static ssize_t (*libc_write)(int, const void *, size_t) = 0;
static ssize_t write_pos = 0, pos = 0;
ssize_t r;
// Get libc write function address.
if( !libc_write )
libc_write = dlsym(RTLD_NEXT, "write");
// Call libc write.
r = libc_write(fd,buf,count);
// If FD == 1 (stdout), output to FD 2 (stderr) the current position
if( fd == 1 )
{
// store errno
int saved_errno = errno;
if( r == -1 )
write(2,"Error\n",6);
else
{
pos += r;
if( pos > write_pos )
{
char buf[48];
snprintf(buf,48,"stdout:%ld\n",pos);
write(2,buf,strlen(buf));
// Write only after 1000000 bytes
write_pos = pos + 1000000;
}
}
errno = saved_errno;
}
return r;
}
// ------------ end -----------
Más información sobre la lista de distribución Linux