[ Milan Aksic @ 02.06.2001. 19:22 ] @
Kako da (i dali moze) C/C++ program kopira samog sebe? Ja sam kao pocetnik pokusao sa funkcijom atexit() ali bez vidnog rezultata. Da li neko zna resenje?
Poz.
[ Vojislav Milunovic @ 02.06.2001. 21:54 ] @
Nerazumem sto ti nije uspleo ali evo ti kod :

#include<sys/types.h>
#include<sys/mman.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>

int main(int argc,char **argv){
void *addr;
int fd,fd_tmp;
struct stat buf;
stat(argv[0],&buf);
fd=open(argv[0],O_RDONLY);
fd_tmp=open("/tmp/samog_sebe",O_CREAT|O_TRUNC|O_WRONLY,0111);
addr=mmap(NULL,buf.st_size,PROT_READ,MAP_SHARED,fd,0);
write(fd_tmp,addr,buf.st_size);
munmap(addr,buf.st_size);
close(fd);
close(fd_tmp);
}

I sada si prekopirao sav taj kod u neki drugi file ili drugim recima samo sebe u nejki drugi file
[ Milan Aksic @ 02.06.2001. 22:18 ] @
Hvala predator, ali da li bi mogao da mi pomognes oko programa za DOS ili Windows, i s'obzirom da sam pocetnik da mi, ako mozes, malo pojasnis kod.
Pozdrav.
[ Vojislav Milunovic @ 03.06.2001. 13:22 ] @
Za windows/dos ne znam ali evo da ti pojasnim sta sam kuckao za UNIX :

otvoris samog sebe tj argv[0] i taj file mapiras u memoriji sa mmap() tj. ceo file kao da si ubacio u memoriju.
Zatim sam sa drigim open() otvorio file /tmp/samog_sebe i u njega sa write() prepisao sadrzaj memorije tj. tog mapiranog filea ;o)
Pod DOSom mozes da probas da koristis blockove od po 4096 (ili vece zbog brzine(sto je veci block to se manje poziva rerad/write u toku programa)) byte za kopiranje.

Algoritam:
1: Otvori 2 file 1. samog sebe 2. file u koji ces da kopiras
2: Alociraj sa malloc(4096);
3: Sa read() protictaj 4096 byte iz prvog filea i sa write() ih upisi u drugi
int rd=read(fd,buf,4096);
write(fd,buf,rd);
4: ponavljas postupak dok read != 0 (tj. kraj filea) ili != -1 (greska)
5: zatvro oba file descriptora i to je to.

---------
p.s. Ovako nesto bi trebalo da radi u DOSu
[ Milan Aksic @ 03.06.2001. 20:00 ] @
Hvala predator :) Ovo mi je u Linuxu uspelo, ali pokusacu da napravim i DOS ili Winu.
Pozdrav.
[ Makojdis @ 03.06.2001. 21:19 ] @
U windozi ovo ne radi
[ Vojislav Milunovic @ 03.06.2001. 21:37 ] @
Ne znam nisam se igrao sa Winom pa ne znam ni kako bi se nesto ovako uradilo u njemu ;o)
[ Mikky @ 03.06.2001. 22:00 ] @
Citat:
predator je napisao:
otvoris samog sebe tj argv[0] i taj file mapiras u memoriji sa mmap() tj. ceo file kao da si ubacio u memoriju.

1: Otvori 2 file 1. samog sebe 2. file u koji ces da kopiras
2: Alociraj sa malloc(4096);
3: Sa read() protictaj 4096 byte iz prvog filea i sa write() ih upisi u drugi
int rd=read(fd,buf,4096);
write(fd,buf,rd);
4: ponavljas postupak dok read != 0 (tj. kraj filea) ili != -1 (greska)
5: zatvro oba file descriptora i to je to.



e sad ti meni reci
gde si naucio tu proceduru da to uradis
mislim, kada bi meni neko trazio to da uradim ja ne bi imao pojma da trebam prvo da "mapiram fajl u memoriji" i ostalo.....isto tako i kod drugih stvari kao npr. rad sa socketima....treba prvo da kreiras pa da otvoris socket pa da bindujes itd.....
takodje koja je razlika izmedju tog mapiranja i alociranja?

2 pitanje, sta je file descriptor?
3 kako ti definises stream, tj kako ga ti kapiras posto samo programiranje je puno apstraktnih pojmova i treba vremena da se te stvari iskristalishu u glavi......barem kod mene

[Ovu poruku je menjao Mikky dana 06-03-2001 u 10:03 PM GMT]
[ Vojislav Milunovic @ 04.06.2001. 00:24 ] @
Citat:
Mikky je napisao:
e sad ti meni reci
gde si naucio tu proceduru da to uradis
mislim, kada bi meni neko trazio to da uradim ja ne bi imao pojma da trebam prvo da "mapiram fajl u memoriji" i ostalo.....isto tako i kod drugih stvari kao npr. rad sa socketima....treba prvo da kreiras pa da otvoris socket pa da bindujes itd.....


Za pocetak o net programiranju i socketima mozes pogledati ovo:
http://nonenone.2y.net/download/network_programming_tutorial.tgz
Onda mozes da potrazis i
An Advanced 4.4BSD Interprocess Communication Tutorial
Zatim ako oces da se nadjemo u gradu pa da ti dam Advanced programming in UNIX environment...
Imas tu jako dobro poglavlje o signalima (ja sam odatle naucio dosta o primeni/koristi signala),onda imas mmap(),syslog(),open,write/read i gomilu ostalih funkcija...stvarno knjiga koja pokriva sve o UNIX programiranju...

Citat:

takodje koja je razlika izmedju tog mapiranja i alociranja?


Pa alociranje je dobavljanje memorije sa malloc,realloc,calloc i sl...
A ovo mapiranje bi mogao da definisem sa recimo podizanje fajla u memoriju ;o) ili obuhvatanjem jednog dela memorije za moje potrebe ;o)
Ako se nevaram malloc i srodne funkcije preko sbrk() i brk() pokusavaju da alociraju memoriju u data segmentu.
Ovde se pravi razlika jel je mmap() syscall koji sluzi bas za (po srpski) postavljanje filea u memoriju tako da sa njegovim sadrzajem mozes da opstis kao i svakim drugim pointerom.
Ne znam u kom delu memorije se nalazi alocirana memorija sa mmap() ali to nije ni bitno ako se ne bavis kernel hackingom ;o)
Pogledaj ovaj kod de se iz fajla u fajl kopira tako sto dva fajla se mapiraju u memoriji i onda sa memcpy() se kopira:
Code:

#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>

#ifndef MAP_FILE
#define MAP_FILE 0
#endif

int main(int argc,char **argv){
 int fd,fd1;
 void *file1,*file2;
 struct stat buf;
 mode_t mode;
 if (argc!=3){
   printf("Usage %s <src file>  <dst file>\n",argv[0]);
   exit(1);
 }
 stat(argv[1],&buf);
 mode=buf.st_mode;
 fd=open(argv[1],O_RDONLY);
 fd1=open(argv[2],O_CREAT|O_TRUNC|O_RDWR,mode);
 
 lseek(fd1,buf.st_size-1,SEEK_SET);
 write(fd1,"",1);
 
 file1=mmap(0,buf.st_size,PROT_READ,MAP_SHARED,fd,0);
 
 file2=mmap(0,buf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd1,0);
 printf(" copying from %p to %p\n",file1,file2); 
 memcpy(file2,file1,buf.st_size);
 exit(0);
}


Citat:

2 pitanje, sta je file descriptor?


Najobicniji int koji se vrne posle uspesnog open(),mkstemp(),socket() itd...to bi trebalo da predstavlja univerzalni broj u okviru programa kojim bi se identifikovao taj otvoren file(sve je na UNIXu file)

Citat:

3 kako ti definises stream, tj kako ga ti kapiras posto samo programiranje je puno apstraktnih pojmova i treba vremena da se te stvari iskristalishu u glavi......barem kod mene


Pa stream prevashodno shvatam kao FILE * ;o) mozda on ima neko levo znacenje ali ja ga ovako shvatam jel se kaze u man za printf :
Printf() and vprintf() write output to stdout, the
standard output stream; fprintf() and vfprintf() write output to the giv-
en output stream;


A FILE struktura opet ima jednog clana koji na UNIXu pokazuje na fd,(mozda je tako i na DOSu)

[ Makojdis @ 04.06.2001. 12:08 ] @
A jel' moze jednostavno da otvoris program kao datoteku
citas red po red kao stringove ili kao char i upises u drugu....
ako nije mnogo veliki fajl procice brzo

Ili alo radis u win-u napravis bat fajl copy file1 file2 i startujes iz C-a...
[ Vojislav Milunovic @ 04.06.2001. 16:35 ] @
To citanje linju po linju mozes samo sa textualnim fajlovima.
A binarni fajlovi sadrze 0x00 sto predstavlja kraj stringa pa zamisli da neki file ima

Bio jednom jedan covek \x00 (samo 0) koji je imao 10oro dece

Samo ce ti se prekopirati ovo Bio jednom jedan covek. Inace ako se 0x00 nadje jednom u file on je binarni ;o)
probaj pod UNIXom da dodas 0x00 preko nekog HEX editora u neki file i posle otvori taj textualni file sa elvisom i gledaj cuda ;o) dobices hex zapis...drugim recima file je binarni
[ Makojdis @ 05.06.2001. 13:58 ] @
Onda lepo citas znak po znak i boli te uvo za sve
[ Vojislav Milunovic @ 05.06.2001. 17:28 ] @
Mozes ali je sporo
Pogledaj da li ce brze da radi program koji kopira jedan PAGE (4096 byte) ili jedan byte po jedan byte pa javi rezultat
[ Mikky @ 07.06.2001. 16:03 ] @
aj sad da se malo vratimo na sockete

procitao sam malo ono od beej-a
shvatio tu i tamo

nije mi jasno ono byte order
ima neki network i host
1. sta je to u opste i cemu sluzi
2. zasto moram da prebacujem iz jednog u drugi
[ Vojislav Milunovic @ 07.06.2001. 19:23 ] @
To moras da koristis na intelu jel je little endian : Naime on ce port 0x4142 da zapise u memoriju kao
4241 ali u paketu mora da bude 4142 znaci na sistemima gde je big endian tj. 0x4142 se u memoriju pise 4142 te funkcije su definisane kao (iz mana) "On machines which have a byte order which is the same as the network order, routines are defined as null macros." .
Ti uvek koristis ove funkcije zbog kompatibilnosti softwarea na big endian te fje ovako izgledaju:
Code:

#define htons(x) x

dok za little endian njihv opis mozes da nadjes u libc source..

Evo ti primer za to :
Code:

int main(){
 short port = 0x4142; 
 printf("%p\n",port);
 printf("%p\n",htons(port));
}
[ Mikky @ 07.06.2001. 23:35 ] @
Citat:
predator je napisao:
To moras da koristis na intelu jel je little endian : Naime on ce port 0x4142 da zapise u memoriju kao
4241 ali u paketu mora da bude 4142 znaci na sistemima gde je big endian tj. 0x4142 se u memoriju pise 4142 te funkcije su definisane kao (iz mana) "On machines which have a byte order which is the same as the network order, routines are defined as null macros." .
Ti uvek koristis ove funkcije zbog kompatibilnosti softwarea na big endian te fje ovako izgledaju:
Code:

#define htons(x) x

dok za little endian njihv opis mozes da nadjes u libc source..

Evo ti primer za to :
Code:

int main(){
 short port = 0x4142; 
 printf("%p\n",port);
 printf("%p\n",htons(port));
}


ok znaci taj big endian vazi za intel racunare
a ovi ostali tipa macintosh .....i ostali (ja ni ne znam koji jos ostali postoje )
koriste normalan redosled
ok shvatio, samo mi nije jasno sto ti iz intela vecito nesto komplikuju zivot
[ Vojislav Milunovic @ 08.06.2001. 00:58 ] @
Nene intel je little endian jel prvo pise najmanji broj znac 123456789 ce da bude zapisano kao 987654321 dok na big endian (ja mislim da je to SPARC) 123456789 ce da bude 123456789.
Sve u svemu nije bitno koji ti je cpu(big/little),sve do koristis C standarde razlike se ne primecuju.
[ Mikky @ 09.06.2001. 02:26 ] @
Citat:
predator je napisao:
Nene intel je little endian jel prvo pise najmanji broj znac 123456789 ce da bude zapisano kao 987654321 dok na big endian (ja mislim da je to SPARC) 123456789 ce da bude 123456789.
Sve u svemu nije bitno koji ti je cpu(big/little),sve do koristis C standarde razlike se ne primecuju.


ok cek sad
imamo
little endian - intel - u memoriji stoje obrnuto
big endian - ostali tj ne-intel - u memoriji stoje normalno

e sad koji od njih je host byte order a koji network
i jos nesto, gore si napisao 123456789
ne znam da li si mislio na hex (predpostavljam da jesi)
zar ne bi trebalo da stoji ovako
21 43 56 87 9.....
znaci byte po byte obrcem a ne ceo niz?
[ Vojislav Milunovic @ 09.06.2001. 08:32 ] @
Pa network byte order je big endian ;o)
Inace ovo 123456789 sam bas muislio bukvalno da vidis kako je taj broj predstavljen u memoriji je 987654321 inace 0x12345678 bi u memoriji bilo 78563412 jer je 78 poslednji byte i on se u meoriji pise kao prvi pa onda 56 kao drugi 34 kao treci i 12 kao poslednji.
Naime zbog ovo little enidana imas dobar text u Phrack55 ili 56 gde se opsiuje exploitovanje buffer overflowa za jedan byte. tako da 0xbfffffff kad overflowujes sa 0 dobijes 0xbfffff00 a na big endian bi obrisao prvi byte 0x00ffffff i ne bi ti uspelo to.

Pouzdano znam da je intel little endian a za ostale CPU ne znam.To nije ni bitno za C programere