maślak nastukał:
> Proszę, wydrukuj sobie i powieś nad łóżkiem.
I w rezultacie trzeba "rescue" dla prawie każdej operacji. Porównaj z wycinkiem kodu na końcu mojego posta.
> Niewiem czy pracowałeś "w zawodzie" jako developer z szefem i project
> menagerem nad głową.
Aplikacyjek dla klientów nie zwykłem pisać z racji bycia adminem. Co napiszę udostępniam na licencji BSD i jak dotąd kilka osób dziękowało mi za nie.
Aplikacyjkę napisałem jedną, panel kliencki do hostingu. Z tym jest problem taki, że wymaga sporo operacji z uid 0. W rezultacie, panel pisany w pehapcu wywołuje suidy w C, które mu ufać nie mogą. Za wiele roboty to nie było, ale trzeba było się dobrze zastanowić na jakie sposoby skompromitowany użytkownik "panel" mógł próbować nadużyć przywileje wywołując suidy. I jak użytkownik mógł spreparować drzewo katalogów.
Najwięcej nawściekałem się na PHP, w którym nie dało się pisać tak:
code:
if open fd == -1
goto bail1
if read fd == -1
goto bail2
if open fd2 O_WRONLY|O_CREAT|O_EXCL == -1
goto bail2
if write fd2 == -1
goto bail3
[...]
return 0
[...]
bail3:
unlink fd2
close fd2
bail2:
close fd
bail1:
return -1
z racji konieczności przeprowadzania czasem operacji na plikach. Za to trzeba było pisać tak:
code: if open fd == -1
return -1
if read fd == -1
close fd
return -1
if open fd2 O_WRONLY|O_CREAT|O_EXCL == -1
close fd
return -1
if write fd2 == -1
close fd
close fd2
unlink fd2
return -1
co przyprawiało mnie o dreszcze :-)
> W takiej sytuacji nie ma czasu i nie wypada
> męczyć Wacława nad cudownym kodem. Aplikacja zazwyczaj ma działać
> na wczoraj. Niestety geekować da się tylko po godzinach.
Mój kod nie jest idealnie ustrukturyzowany i nie posiada odpowiednich metod abstrakcji, ale nie znoszę:
1) nie sprawdzania wyniku wywołań systemowych
2) nie sprawdzania podanych przez użytkownika danych na metaznaki, które później są przekazywane do "sh -c" exec() w php czy jako zapytanie SQL.
3) nie dbanie o atomowość i jednoczesność przy operacjach na plikach.
Nie każdy kod musi być idealnie napisany, ale niektóre gatunki partactwa jak wyżej wymienione to szczyt szczytów :-)
Nawiązując do 3): z SQL atomowość i jednoczesność nie jest problemem, nawet jeśli zna się go w tak niewielkim stopniu jak ja. Ostatnio pisałem prostą bazę SQLite na hashe md5 obrazków dołączanych w spamie. Tak jak kiedyś męczyłem się z operacjami na plikach, tak w SQLite mogę zrobić:
code:
foreach my $file (@ARGV) {
[...]
my $tran = tran_start($dbh) or goto bail;
{
my ($ret) = query_fetch($dbh, q#SELECT rowid FROM sig where md5 = ? AND size = ?#, $md5, $size);
defined $ret or goto bail;
if ($ret) {
$sigid = $ret->{'rowid'};
} else {
query_do($dbh, q#INSERT INTO sig (md5, type, whitelistp, size) VALUES (?, ?, ?, ?)#, $md5, INDEX_IMAGE, 0, $size) or goto bail;
my ($fields) = query_fetch($dbh, q#SELECT rowid FROM sig WHERE md5 = ? AND (? IS NULL OR ? = size)#, $md5, $size, $size);
defined $fields or goto bail;
unless ($fields) {
warn "can't happen: stored entry doesn't exist";
goto bail;
}
$addp = 1;
$sigid = $fields->{'rowid'};
}
my ($lcount) = query_fetch($dbh, q#SELECT COUNT() FROM log where sig = ? AND log = ?#, $sigid, $path) or goto bail;
if ($lcount->{'COUNT()'} == 0) {
query_do($dbh, q#INSERT INTO log (sig, time, log) VALUES (?, ?, ?)#, $sigid, time, $path) or goto bail;
}
}
tran_commit($dbh) or goto bail;
$addcnt++ if $addp;
next;
bail:
$failcnt++;
do_nothing:
tran_rollback($dbh) if defined $tran;
Cud-miód normalnie, no.
__________________
sort the flock (then, warn the "goats" & kill the "sheep");
kill them, dump qualms, shift moralities,
values aside, each one; die sheep! die to reverse the system
you accept (reject, respect);
Edytowane przez weirdo dnia 10-12-2006 o godz. 13:23
Zgłoś post do moderatora | IP: Zalogowane
|