lunes, 29 de diciembre de 2008

VMware 1.0.8-126538 en kernels nuevos, una odisea

Actualizacion: los problemas de vmmon descriptos en este articulo y algunos mas se resolvieron en el patch que publico y describo en este post

Desde hace unas semanas que me hice un tiempo e instale fedora 10 con kde4 y toda la magia, pero llego el momento en que necesite virtualización, ahí empezó una entretenida historia (entretenida ahora que termino bien :D )
Si algunos de los que están leyendo esto comparten la experiencia de haber intentado instalar la ultima versión de VMware en uno de los últimos linux con el kernel 2.6.27.9 o alguna versión parecida, (encontré foros de personas que decían que este mismo problema pasa también en el ultimo ubuntu, seguro en otras distribuciones tambien ), habrán leído en la pantalla unas groserías particulares, cuando ejecutaron el famoso vmware-config.pl:

"/tmp/vmware-config1/vmmon-only/./include/compat_semaphore.h:23:27: error: asm/semaphore.h: No such file or directory"
"/tmp/vmware-config24/vmmon-only/linux/driver.c:153: error: se especificó el campo desconocido ‘nopage’ en el inicializador"

y asi...

No aguante mas y entre a meter mano en el codigo, primero lo del semaphore.h, no era complejo, simplemente cambiaron al .h de lugar, ahora esta en linux/semaphore.h en lugar de asm/semaphore.h en el nuevo kernel:




#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#include "asm/semaphore.h"
#else
#include "linux/semaphore.h"
#endif



respecto a lo de nopage, no se bien que significa :(, lo unico que hice fue comentar las dos lineas que causaban problemas:


...

static void LinuxDriverPollTimeout(unsigned long clientData);

static struct vm_operations_struct vmuser_mops = {
// .nopage = LinuxDriverNoPage
};

struct vm_operations_struct vmuser_locked_mops = {
// .nopage = LinuxDriverLockedNoPage
};

static struct file_operations vmuser_fops;
static struct timer_list tscTimer;

...


Tomar nota de esto ultimo, queda pendiente evaluar el significado de todo eso


Y eso no fue todo, como todo un clásico de la programación C, al corregir errores, el compilador revela los otros errores que antes no se mostraron al no llegar a compilar esas secciones, quedo un desbarajuste en la función smp_call_function, que según el smp.h del kernel, tomaba 3 argumentos, y en driver.c y hostif.c del codigo fuente de vmmon, lo llamaba pasando 4 parámetros, a esto, lo resolvi eliminando el tercer argumento de todas las llamadas a la función smp_call_function ( y compat_smp_call_function, que era un sinónimo en ese código ). Elimine el tercer parametro porque en la definición de la funcion smp_call_function en el código del kernel mas viejo era el "retry" el tercer parámetro extra que había demás en relacion al nuevo



// version nueva EN linux/smp.h

/*
* Call a function on all other processors
*/
int smp_call_function(void(*func)(void *info), void *info, int wait);

// version vieja en linux/smp.h

/*
* Call a function on all other processors
*/
int smp_call_function(void(*func)(void *info), void *info, int retry, int wait);



Por ultimo, queda una llamada a kill_proc en linux/hostif.c, que segun el compilador no existe un kill_proc definido, ahi simplemente comente la linea :p

Y por ultimo, al compilar vmnet, surge el mismo problema del semaphore.h, la solución es exactamente la misma que con la compilación del otro modulo

Al final funciono todo, al punto que compilo todo, pude configurar todo lo que necesite y pude crear y bootear una maquina virtual, si embargo dos cosas (que habia mencionado antes) quedaron atadas con alambre:

1) el .nopage = LinuxDriverNoPage comentado casi al principio de linux/driver.c
2) el kill_proc comentado casi al final de linux/hostif.c
3) La version del kernel que no supe precisar en el #if que incluye el semaphore.h

Disculpen no haber subido el parche que genere, pero esos últimos dos puntos me parece que quedaron muy truchos y no quiero que cause problemas tratándose este código que toque de nada mas y nada menos que de módulos del kernel

Lo probe un poco, y al parecer el cambio del kill_proc genera algunos problemas, ya que al correr la mayoria de las maquinas virtuales, vmserverd termina por un error causado en el kernel,

con este problema:

Kernel failure message 1:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
IP: [<0000000000000000>] 0x0
PGD 12944067 PUD 12942067 PMD 12941067 PTE 0
Oops: 0010 [1] SMP

y con este backtrace:

[] ? HostIF_SetFastClockRate+0xb0/0x137 [vmmon]
[] Vmx86_SetHostClockRate+0xb4/0xc9 [vmmon]
[] LinuxDriver_Ioctl+0x3d3/0x923 [vmmon]
[] ? inode_has_perm+0x5b/0x61
[] ? __dequeue_entity+0x61/0x6a
[] ? remove_wait_queue+0x2f/0x39
[] ? file_has_perm+0x83/0x8e
[] LinuxDriver_CompatIoctl+0x2b/0x40 [vmmon]

Fijense que la funcion con problemas, es la que modifique comentando el kill_proc, se resolveria cuando encuentre una implementacion de kill_proc que use las posibilidades de este nuevo kernel

Después de un rato, corregí la función , reemplazando a kill_proc por su equivalente el nuevo kernel, tal como explica en esta pagina , cuando compilo, siguió existiendo el mismo error, buscando por la web, encontré algo acerca de please revert commit 53f1b1433da7eac2607a4...; aparentemente, un chabon hizo un commit, que crashea el kernel cuando cierta función se llama de cierta forma, espero que actualizando el kernel cuando se corrija o patcheandolo pueda solventar este problema

viernes, 26 de diciembre de 2008

Extraccion de direcciones de mail de texto en dos lineas

DISCLAIMER: la siguiente información se difunde solo con fines educativos, el blog de NilClass NO fomenta el spam



# El codigo consta de dos chainings,
# el primero abre el archivo y escribe en el
# (todo el codigo hasta el .write inclusive)

# en el primer chaining

# abre el archivo (File.new( "..." , "w") )
# invoca el metodo write

# en el segundo chaining

# abre el archivo, para lectura
# hace un read al archivo, para leer todo su contenido
# hace un split, usando como divisor la expresion regular
# la expresion regular especifica que matchee todo lo que
# no sea ni letra minuscula ni letra mayuscula ni numero
# ni esos caracteres que pueden tener las dir. de mail
# despues el chaining hace un select de los strings que contienen
# el caracter "@"
# y por ultimo, efectua un join uniendo todas las cadenas
# con el caracter de salto de linea (\n) de por medio

ary = File.new("rawtext.txt").read.split(/[^a-zA-Z0-9@._-]/)
File.new("mails-parsed.txt","w").write ary.select{ |x| x =~ /@/ }.join("n")

# nota: esta claro que pude haber hecho todo en una sola linea
# pero lo separe en dos para que quepa en la columna del post

lunes, 22 de diciembre de 2008

Conexion a bases de datos mysql via ruby

Por razones que no vienen al caso encontré e instale una librería para ruby que permite conectarse a los motores de bases de datos mysql, la misma la pueden encontrar en http://www.tmtm.org/en/ruby/mysql/, la libreria se puede usar mas o menos asi:



require "gramas"
require "mysql"
my = Mysql::new("localhost", "username", "password", "database")
res = my.query("select name,surname from users")
res.each do |row|
col1 = row[0]
col2 = row[1]
end

martes, 16 de diciembre de 2008

Como mantener una lista de subclasses en una clase

Definiendo el método de clase inherited, se pueden hacer muchas cosas cuando se hereda una clase, entre ellas esto:


# defino un modulo para agrupar los métodos que se agregan a las clases
module SubclassesRegister
def subclasses
if @subclasses == nil
@subclasses = []
end

@subclasses
end
end

# la clase principal, la que implementa la funcionalidad de registrar las subclases
class RegisteredClass

def self.inherited(x)

# se le agregan los metodos para que mantenga la lista de superclases ( a la superclase de x)
x.superclass.extend SubclassesRegister unless x.superclass.include? SubclassesRegister

# cuando alguna clase hereda de esta, se registra la subclase (si la superclase no es esta)
if x.superclass != RegisteredClass
self.register_subclass(x)
end
end

def self.register_subclass(subclass)

superclass = subclass.superclass
print "registered #{subclass} as subclass of #{superclass}\n"

# agregar la clase subclass a la lista de subclases de su superclase
superclass.subclasses << subclass
end
end

class Animal < RegisteredClass
def self.enu
# puedo obtener las subclases con solo usar el metodo "subclasses"
print "subclases de Animal: #{subclasses.join("; ")}\n"
end
end

class Perro < Animal
def self.enu
# cualquier clase de la jerarquia que extienda directa o indirectamente de RegisteredClass
# puede obtener la lista de sus subclases
print "subclases de Perro: #{subclasses.join("; ")}\n"
end
end

class Terrier < Perro
end

class Dogo < Perro
end

class Gato < Animal
end


Animal.enu
Perro.enu




Espero que les haya sido de utilidad

lunes, 15 de diciembre de 2008

¡¡¡ Aleluya !!!, consegui el Rubik original


Al principio crei que era un sueño, pero lo consegui, con empaque original y todo, en pocas palabras, el de la foto de la derecha
Por si no lo sabian, en Argentina, durante un tiempo importante no hubo distribuidor oficial del cubo Rubik, y ahora es muy dificil de conseguir, y lo consegui.
El cubo es mucho mas maleable que cualquier "imitacion" que se puede conseguir practicamente en cualquier negocio, aparentemente el plastico del que se componen las piezas tiene mayor calidad y por lo tanto dura mas; y los stickers tambien, en el mismo tiempo de uso que en los otros cubos los stickers empezaban a perder el color, este sigue aparentando que no se uso !!!, es increible.
Como bonus tambien me compre uno de 4x4 (code name: The Revenge of Rubik), el de la otra foto



viernes, 12 de diciembre de 2008

La guerra de cookies

No se como describirlo, no se sabe como empiezo, en un instante dado, salto uno diciendo
"Quiero editar cookies", y el otro dijo "No se puede, estan en el server", entonces , el otro dijo... Mejor pongo un guion:

-

Lo siguiente ocurre entre las 12:00 pm y las 13:00 pm

Matt: Quiero setear una cookie
Diego: No se puede, esta en el server
Caco: Podes usar javascript.cookie
Matt: Solo setea localhost, quiero setear para ese host
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Matt: Quiero setear una cookie en el browser
Robert: Miren esto
Diego: Espera
Matt: Espera
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Matt: ¡¡¡Quiero poner la cookie!!!
Robert: Miren esto
Diego: Espera
Matt: Espera
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Matt: ¡¡¡Quiero poner la cookie!!!
Robert: Miren esto
Diego: Espera
Matt: Espera
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Gise: BBAAAAAAAAAAAAASTAAAAAA!!!
Matt: ¡¡¡Quiero poner la cookie!!!
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Matt: ¡¡¡Quiero poner la cookie!!!


for i in (1..3000)
print "Diego: NO se puede\n"
print "Matt: SI se puede\n"
end


Robert: Miren esto (mostrando el cuadro de agregar una cookie )
Diego: Espera
Matt: Espera. A ver...

Robert: Usa ADD N EDIT COOKIES para Firefox

Matt: Robert encontró lo que quería desde el principio
Diego: ¿eso era?


end

miércoles, 10 de diciembre de 2008

He descubierto una funcion no documentada en dos sistemas operativos: AltTAB ReversO

El fin de semana descubri algo muy loco. ¿ Alguno de ustedes se encontró altabulando en decenas de ventanas en el escritorio , y de repente se dan cuenta de que se pasaron la que querían, y por lo tanto se ven obligados a dar toda la vuelta ?. La solucion esta a milímetros del meñique, mientras mantienen apretada la tecla ALT, presionen y mantengan apretada la tecla SHIFT tambien, cuando presionen TAB, altabulearean en sentido reverso !!
Lo curioso de esta técnica, es que funciona en los escritorios de Windows, en Kde y Gnome (si algún usuario de MacOS esta leyendo esto, por favor que deje un comentario acerca de si esto también sirve en el mundo bizarro) ; no solo eso, también funciona en el navegador Firefox para las pestañas (en este caso la tecla para cambiar de pestañas es control+tab, pero también sigue siendo el poderoso SHIFT, el agente reversor de la funcionalidad )

Esto fue todo por hoy, espero que les haya gustado, chau