23 julio 2009

Moverse por los directorios [Linux]

Holas,
vamos a ver los archivos de los directorios en Linux, no es muy dificil.
primero que todo necesitamos esto:

Código
       #include sys/types.h
#include dirent.h

las carpetas se abren como si fuesen archivos, osea, se abre la carpteas (opendir()) se obtiene en este caso una estructira DIR, dsp se va leyendo cada uno de los archivos (o carpetas) que contiene la carpeta abierta (readdir()) y cuand terminamos lo cerramos (closedir())

enpezamos con opendir:
DIR *opendir(const char *name);
en "name" ponemos la ruta de la carpeta
solamente tenemos que hacer
Código
#include sys/types.h
#include dirent.h

DIR *d;
d = opendir("/usr/bin");

si opendir retorna 0, hubo error, y podemos visitar errno para averiguar que error es.

ya tenemos abierto el directorio, ahora con readdir:
struct dirent *readdir(DIR *dir);
*dir es lo que nos retorno opendir, y readdir nos da una estructura dirent con informacion de lo que hay en la carpeta. readdir va retornando de a uno, osea, la primera vez que se llama a readdir nos da la primera carpeta (".") la proxima vez que lo llamemos nos da la segunda carpeta ("..") y la tercera vez nos da la tercersera, y asi sucesivamente, cuando no haya mas archivos en el directorio, readdir retorna 0.
dirent esta definida asi:
Código
          struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file */
char d_name[256]; /* filename */
};
en d_name tenemo el nombre del archivo, y en d_type el tipo de archivo (comun, directorio, pila, socket, etc.), pero "man" nos dice esto:
Citar
Other than Linux, the d_type field is available mainly only on BSD sys-
tems. This field makes it possible to avoid the expense of calling
stat(2) if further actions depend on the type of the file. If the
_BSD_SOURCE feature test macro is defined, then glibc defines the fol-
lowing macro constants for the value returned in d_type:

DT_UNKNOWN The file type is unknown.

DT_REG This is a regular file.

DT_DIR This is a directory.

DT_FIFO This is a named pipe, or FIFO.

DT_SOCK This is a Unix domain socket.

DT_CHR This is a character device.

DT_BLK This is a block device.

If the file type could not be determined, the value DT_UNKNOWN is
returned in d_type.
(en resumen, dice que d_type es está principalmmente por BSD, si se define la macro _BSD_SOURCE, el compilador va a definir toda esa lista de tipos)

asique nose.. a tener cuidado (al final de este post explico stat())

para usar a readdir():
Código
#include sys/types.h
#include dirent.h

DIR *d;
struct dirent *dire;
d = opendir("/usr/bin");
if(!d)
return 1; /*error, upsss*/
while((dire = readir(d)) != 0)
printf("/usr/bin/%s", dire->d_name);
noten que utilizo dire->d_name porque dire es un puntero a una estructura..

muy bien, ahora para cerrar el directorio
int closedir(DIR *dir);
no hay mucho que decir..., solo que en caso de error retorna -1
Código
#include sys/types.h
#include dirent.h

DIR *d;
struct dirent *dire;
d = opendir("/usr/bin");
if(!d)
return 1; /*error, upsss*/
while((dire = readir(d)) != 0)
printf("/usr/bin/%s", dire->d_name);
closedir(d);

que facil no?
bueno, hay mas funciones, solo voy a explicar rewinddir, no creo que las otras sean necesarias, cualquier cosa pueden recurir a "man"
void rewinddir(DIR *dir);
rewinddir() (como el nombre lo dice) se coloca al principio del directorio, asi la proxima llamada a readdir va a dar como resultado el primer archivo.


ahora a explicar stat()

#include sys/types.h
#include sys/stat.h
#include unistd.h

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);


stat y fstat son lo mismo, la diferencia es que a stat() le indicas el nombre del archivo/carpeta y en fstat le indicas un descriptor de archivo/carpeta (la funcion open() tambien abre carpetas...)

lo que hace stat es colocar en "buf" informacion sobre el archivo especificado, y la informacion es:
Código
           struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};

no hay que aclarar mucho, solo especifico a la variable st_mode:
(estas son bit flags)

Citar
S_IFMT 0170000 bit mask for the file type bit fields
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 0004000 set UID bit
S_ISGID 0002000 set-group-ID bit (see below)
S_ISVTX 0001000 sticky bit (see below)
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission

osea, por ejemplo para saber si es un directorio hay que hacer

Código
if(st_mode & S_IFDIR)
/*es directorio!*/
else
/*no lo es :(*/

(lo mismo para saber quieens tienen permisos de hacer que con el archivo, solo hay que usar el AND)
o bien, utilizar unas macros que nos brinda
Citar
S_ISREG(m) is it a regular file?

S_ISDIR(m) directory?

S_ISCHR(m) character device?

S_ISBLK(m) block device?

S_ISFIFO(m) FIFO (named pipe)?

S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)

S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
domde en "m" ponemos st_mode y nos retornan != de 0 si es correcto o == a 0 si es falso



bueno, creo que eso es todo...

salu2!

18 junio 2009

Array de funciones

Hola, vamos a ver algo muy loco, algo que nose si en otros lenguajes se pueda, pero en C obiamente SI Lengua

hace un tiempo descubri q se podia hacer esto y me quede xD :S :'( :P :O :O :O :Sonrisa :Sonrisa Huh? Huh? Impresionado Impresionado Impresionado Impresionado xDDD

/**********************************************************/


#include "stdio.h"

typedef int (*_func)(char *, ...);
_func func[10];

int main(void)
{
func[5] = (_func)printf;
func[5]("hola mundo!\n");
getchar();
return 0;
}
/**********************************************************/


utilize func[5] solo para demostrar que estoy trabajando con el array Lengua

no puse getchar dentro del array porque getchar esta declarado diferente que printf...
veamos una utilidad buena para esto del array de funciones:

/**********************************************************/
#include "stdio.h"

typedef float (*_func)(float, float);

float add(float a, float b)
{
return a + b;
}

float sub(float a, float b)
{
return a - b;
}

float mul(float a, float b)
{
return a * b;
}

float div(float a, float b)
{
if(b == 0)
return 0;
return a / b;
}

/*cargamos nuestro vector de funciones...*/
_func func[4] = {add, sub, mul, div};

int main(void)
{
int num = 0;
float a,b;
printf("Ingrese 2 numeros\n");
scanf("%f %f", &a, &b);
while(num > 4 || num < 1){
printf("1 - Sumar\n2 - Restar\n3 - Multiplicar\n4 - Dividir\n");
scanf("%d", &num); /*gracias Anibal xD*/
}
num--;
/*por el metodo "tradicional" tendria que venir un switch o varios ifs...*/
printf("Resultado: %f\n", func[num](a, b));
while(getchar() != '\n'); /*la forma que utiliza Ramc para vaciar el buffer xD*/
getchar();
}



/**********************************************************/

bueno, eso es todo, creo q es facil de entender

salu2!

P.D: pufff hace cuanto q no posteaba en C!! xD

21 mayo 2009

Puntos de un circulo

Hola, volviendo a los codigos en C
aca una funcion "matematica", te devuelve en un array todos (la cantidad pedida) los puntos que pertenecen a un circulo de radio X. Si quieren dibujar un circulo en la pantalla es recomendable usar una funcion especifica para eso, pero si quieren saber los puntos en coordenadas X,Y pueden usar mi funcion Lengua

/***********************************/

#include "math.h"
#ifndef PI
#define PI 3.14159265358979323846
#endif

typedef struct {
double x;
double y;
}pxy;

void circulito(double rad, double x, double y, int p, pxy *v)
/*
rad = radio
x,y = centro del circulo
p = puntos a copiar
v = vector donde colocar los puntos
*/

{
double radp = 0, m = 0;
int i;
m = 2 * PI / p;
for(i = 0; p > i; i++){
v[i].x = cos(radp) * rad + x;
v[i].y = sin(radp) * rad + y;
radp += m;
}
}
/*****************************************/

un ejemplo usando la funcion circulito:

/*****************************************/
#include "stdio.h"
/*
suponiendo que tienen la funcion circulito aca arriba
o que la pusieron en un archivo .h e incluyero ese archivo..
*/

int main(void)
{
pxy asd[4];
int i;
circulito(10,5,5,4,asd);
for(i = 0; i != 4; i++)
printf("%.5f %.5f\n", (float)asd[i].x, (float)asd[i].y);
/*leer aclaracion abajo*/

getchar();
return 0;
}
/********************************************/
ese programita les muestra puntos 4 puntos de un circulo de radio 10 y con centro en las coordenadas 5;5 si hacen las cuentas van a ver quer son correctos, dsp pueden probar con 10 puntos o 100 puntos.
en el printf tengo que hacer (float)asd[ i ].x porque sino me muestra muchos decimales o cosas raras, parece que printf trabaja con float

salu2!

01 mayo 2009

Crysis, el mejor juego de la historia

Hola, tengo que hacerle un post a este juegazo, se lo merece.

Crysis, de la empresa Crytek








es EL MEJOR JUEGO QUE JUGE EN MI VIDA!!! exelentes graficos, demaciados buenos, la historia buenisima, estas en una isla japonesa con alienijenas, el final esta muuuyyy buenooo. Una de las cosas que me gusto es que tenes el mapa para vos, no es onda el Gears Of War que tenes que seguir siempre el mismo camino, aparte de que podes resolverlas misiones a lo rambo o a lo hitman o como se te antoje.
tenes un traje especial con un par de poderes, como velocidad, escudo, fuerza e invisibilidad, caes en la isla y te enfrentas a japoneses, y pasando la mitad del juego luchas contra aliens.
los efectos especiales muy buenos, cuando llegen al final aprecien los efectos que tiene!

es uno de los pocos juegos por el que pagaría el doble!!

bueno, le tenia que dedicar un post al juego xD

salu2!

17 abril 2009

Importar funciones de windows en FASM "manualmente"

Hola,
todos seguramente para llamar a una API (como puede ser MessageBox() ) utilizan

Código:
invoke MessageBox,0,"hola","hola",0
y listo, pero hay otra forma mas compleja y que sirve "en casos de emergencia" que esta buena conocer, aparte de que se entiende un poco mejor la forma de trabajar windows con sus .exe
y si ya se piensan que voy a salir con "LoadLibrary" y "GetProcAddress" lamento decirles que no xD es mas complejo que eso.

lo que yo hize y averigue es para el FASM, pero debe de ser muuy parecido para otros compiladores

lo que vamos a hacer es crear una nueva seccion dentro del ejecutable donde vamos a poner determinada informacion para que cuando ejecutamos el .exe el windows automaticamente carge las DLLs y las direcciones de memoria de las funciones..

este es un ejemplo, creo que bastante claro, crea una ventanita con MessageBox() y llama a ExitProcess()
lo importante de todo esta al final, donde empieza la seccion .idata

;------------------------------------------------------------------;
format PE gui

entry main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section '.text' code readable executable

main:
;aca empiezan los argumentos de MessageBox
;(se empieza por el ultimo argumento)
push 0 ;MB_OK
push hi ;texto
push hi ;texto
push 0 ;HWND_DESKTOP
call [MessageBox]
;fijense que uso [nombre], no como el invoke que no utiliza []

push eax ;salimos con lo que retorno MessageBox
call [ExitProcess]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section '.data' data readable writeable

hi db 'hola mundo!',0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;aca viene lo interesante!
section '.idata' import data readable writeable

dd 0,0,0, rva kernel_name, rva kernel_table
dd 0,0,0, rva user_name, rva user_table
;dd 0,0,0, rva dll_name, rva dll_table
;etc.
dd 0,0,0,0,0

;aca es donde se va a cargar
;la direccion de memoria de la funcion
kernel_table:
ExitProcess dd rva _ExitProcess
;LoadLibrary dd rva _LoadLibrary
;etc.
dd 0 ;para terminar la tabla

kernel_name db 'kernel32.dll',0

;aca le indicamos el nombre
;de las funciones que aparecen en la tabla
_ExitProcess dw 0
db 'ExitProcess',0
;_LoadLibrary dw 0
;db 'LoadLibraryA',0

;lo mismo pero para user32
user_table:
MessageBox dd rva _MessageBox
dd 0

user_name db 'user32.dll',0

_MessageBox dw 0
db 'MessageBoxA',0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;------------------------------------------------------------------;

fijense que lo que hacemos es crear manualmente la seccion de importacion, estamos indicandole byte por byte que es lo que tiene que escribir en esa seccion, por lo que se puede hacer con cualquier compilador (con sus respectivas nomenclaturas obiamente)

section '.idata' import data readable writeable
esas son las características de la sección
dentro de esa seccion primero colocamos el nombre de la DLL (la direccion donde esta el nombre) y donde esta la tabla, fijense que uso "rva", eso indica que en vez de colocar la direccion en memoria, coloque la direccion dentro del archivo.

creo que la estructura de la seccion es facil de entender con ese ejemplo, puse entre comentarios como agregar mas funciones o mas dlls.


no es muy practico si podemos hacerlo de la forma facil, pero creo que es interesante (por lo menos para mi lo fue), se tiene mas control sobre el archivo y se aprende mas sobre el formato PE de los .exe

salu2! Cheesy