Superuser

Autor Thema: Erzeugung einer Binärdatei fester Größe mittels Kommando dd  (Gelesen 5338 mal)

Offline escimo

  • Sobl Guru
  • *****
  • Beiträge: 1674
  • SPARCstation 2
    • Youtube-Kanal opensparcbox.org
Hallo zusammen,

ich habe gerade ein "Hänger" mit dem Kommando /usr/bin/dd.

Hintergrund: ich möchte eine aus zufällig generierten (Binär-)Daten bestehende Datei, die eine feste Größe im Dateisystem aufweist, um es als Anhang mittels dem Kommando mailx an eine beliebige Adresse zu versenden.

Dabei habe ich die Auswahl zwischen folgenden "if"-Optionen (input files):
  • /dev/random -> ../devices/pseudo/random@0:random
  • /dev/urandom -> ../devices/pseudo/random@0:urandom
  • /dev/zero -> ../devices/pseudo/mm@0:zero

Nun mit folgenden Kommando kann ich dann eine Datei fester Größe generieren:

$> dd bs=512 count=2 if=/dev/zero of=zerofile
2+0 records in
2+0 records out
$> ls -l zerofile
-rw-r--r--   1 sschaars staff       1024 Jan 31 11:57 zerofile
$> dd bs=8b count=2 if=/dev/zero of=zerofile
2+0 records in
2+0 records out
$> ls -l zerofile
-rw-r--r--   1 sschaars staff       8192 Jan 31 11:58 zerofile
Gut die Datei (Größe="2+0" Blöcke) hat die gewünschten Größen (8b=8x512byte Blöcke) aber enthält natürlich keinerlei zufällig generierte Daten.

Nun dachte ich mir, mit /dev/(u)random müsste sich die Erzeugung einer Binärdatei fester Größer doch bewerkstelligen lassen:
$> dd bs=512 count=2 if=/dev/random of=randomfile
0+2 records in
0+2 records out
$> ls -l randomfile
-rw-r--r--   1 sschaars staff       170 Jan 31 12:10 randomfile
$> dd bs=8b count=2 if=/dev/random of=randomfile
0+2 records in
0+2 records out
$> ls -l randomfile
-rw-r--r--   1 sschaars staff       2080 Jan 31 12:11 randomfile
170 Bytes?  ??? Ich habe hier 1024 Byte erwartet. Was habe ich nicht beachtet?

Grüße
escimo


EDIT: Ich lese mir nochmal die Manpages dazu durch:

$> man -s 7d random
« Letzte Änderung: 31. Januar 2008, 12:36:25 von escimo »

sonnenblen.de - Das unabhängige Sun User Forum


paraglider242

  • Gast
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #1 am: 31. Januar 2008, 12:54:22 »
Habs grad eben versucht (auf Solaris 10 SPARC), sowohl bei /dev/random als auch bei /dev/urandom stimmt die Groesse bei mir genau...

Offline Ten Little Indyans

  • Sobl Bachelor
  • ***
  • Beiträge: 218
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #2 am: 31. Januar 2008, 13:04:34 »
Ich konnte Dein Problem hier nicht reproduzieren.

$ uname -rsv
SunOS 5.8 Generic_108528-22

$ dd bs=512 count=2 if=/dev/random of=randomfile
2+0 records in
2+0 records out

$ ls -l randomfile
-rw-r--r--   1 edi      edi         1024 Jan 31 12:34 randomfile

Apropos manpage, da war mir folgendes aufgefallen:

Zitat
If  there  is  no entropy to produce the requested number of
bytes,  /dev/random  blocks  until  more  entropy   can   be
obtained.

Du hast ja zwei unvollständige Leseoperationen bekommen (0+2 records), also jeweils weniger als die erwarteten 512 Byte. dd macht also offenbar ein non-blocking read und wenn /dev/random sagt ich hab nichts mehr dann ist Schluss.

Keine Ahnung wie man am besten mehr Entropy erzeugt - wahrscheinlich muss auf der Kiste einfach nur genug los sein. Vielleicht vorher einfach einen fiesen Job im Hintergrund starten. ;D

Offline escimo

  • Sobl Guru
  • *****
  • Beiträge: 1674
  • SPARCstation 2
    • Youtube-Kanal opensparcbox.org
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #3 am: 31. Januar 2008, 15:18:34 »
Aha,

vielen Dank für die Infos. Das habe ich in der Manpage zu /dev/random wohl überlesen. ;)

Mmm ... ich habe jeweils ein Kommando vor kurzem noch einmal auf den Servern (Linux/x86 und Solaris/SPARC) abgesetzt. Jetzt stimmen die Dateigrößen bis auf einen Server plötzlich. Das sind eigentlich alles Server, die unter Dauerfeuer stehen. Das will wer verstehen ???

Auf dem Linux-Server reicht die erzeugte Entropy-Datenmenge dann wohl noch nicht aus:
$> dd count=2 if=/dev/random of=randomfile
0+2 records in
0+1 records out
$> ls -l randomfile
-rw-r--r--  1 sschaars inet 191 2008-01-31 14:56 randomfile
$> uname -a
Linux xxxxxxxx 2.6.5-7.282-bigsmp #1 SMP Tue Aug 29 10:40:40 UTC 2006 i686 i686 i386 GNU/Linux

Bei der obigen Ausgabe hat dd dann wohl ein Block in der Ausgabe "verschluckt"? ;)

Auszug aus der Manpage zu "dd":
Zitat
     >0       An error occurred.

     If an input error is detected and the noerror conversion has
     not been specified, any partial output block will be written
     to the output file, a diagnostic message  will  be  written,
     and  the  copy operation will be discontinued. If some other
     error is detected, a diagnostic message will be written  and
     the copy operation will be discontinued.

Gruß
escimo
« Letzte Änderung: 31. Januar 2008, 15:22:41 von escimo »

Offline Toktar

  • Sobl Master
  • ****
  • Beiträge: 333
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #4 am: 31. Januar 2008, 16:59:06 »
Unter Linux füllt sich die Entropy über verschiedenste Input. Wird /dev/random aber abgerufen, verringert sich die Entropy.
Zu sehen über avail_entropy im Proc-Dateisystem.
Ist diese zu gering, wird die Ausgabe gesperrt.

Im Linuxmagazin (http://linuxmagazin.de/heft_abo/ausgaben/2006/11/kern_technik?category=0) war dazu mal ein prima Artikel. Ich hab den allerdings nur in der Printausgabe vollständig.
Toktar
--
Jawoll!
Und DNS braucht's nicht, das ist was fuer Weicheier, die sich keine Zahlen merken koennen.
[Karlheinz Boehme in dcsf]

mdjr

  • Gast
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #5 am: 31. Januar 2008, 20:27:07 »
Hintergrund: ich möchte eine aus zufällig generierten (Binär-)Daten bestehende Datei, die eine feste Größe im Dateisystem aufweist, um es als Anhang mittels dem Kommando mailx an eine beliebige Adresse zu versenden.

Wie wäres es mit ver Verwendung von C-Code anstatt /usr/bin/dd ?

(Gut, gebe zu, dass es nicht einfach ist, einen guten Zufallszahlengenerator zu schreiben.)

Martin

Offline escimo

  • Sobl Guru
  • *****
  • Beiträge: 1674
  • SPARCstation 2
    • Youtube-Kanal opensparcbox.org
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #6 am: 02. Februar 2008, 02:08:14 »
Unter Linux füllt sich die Entropy über verschiedenste Input. Wird /dev/random aber abgerufen, verringert sich die Entropy.
Zu sehen über avail_entropy im Proc-Dateisystem.
Ist diese zu gering, wird die Ausgabe gesperrt.
Oha, das werde ich nächste Woche mal überprüfen. Danke Toktar.

Wie wäres es mit ver Verwendung von C-Code anstatt /usr/bin/dd ?

(Gut, gebe zu, dass es nicht einfach ist, einen guten Zufallszahlengenerator zu schreiben.)
Hallo Martin, ja das wäre in der Tat eine recht anspruchsvolle und durchaus interessante Aufgabe, für die ich aber leider auf Arbeit kaum Zeit bekommen würde und privat habe ich mehr als genug "waghalsiger" und "übergewichtiger" Software-Vorhaben. ;)

Gruß
escimo


mdjr

  • Gast
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #7 am: 02. Februar 2008, 17:00:03 »
Hallo Martin, ja das wäre in der Tat eine recht anspruchsvolle und durchaus interessante Aufgabe, für die ich aber leider auf Arbeit kaum Zeit bekommen würde und privat habe ich mehr als genug "waghalsiger" und "übergewichtiger" Software-Vorhaben. ;)

/* File myrandom.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/times.h>

int main(int argc,char **argv)
{
    unsigned char sds[]={13,17,19,23,29};
    int i,j,s,v;
    struct tms dummy;
    if(argc>1) i=atoi(argv[1]);
    while(argc<2 || i--)
    {
        s=s*sds[4];
        v=times(&dummy);
        for(j=0;j<4;j++) s+=sds[j]*(v>>(8*j));
        putchar(s);
    }
    return 0;
}

myrandom 10000 > myfile.bin

Hat mich jetzt gerade mal 15 Minuten gekostet.

Martin

Offline Toktar

  • Sobl Master
  • ****
  • Beiträge: 333
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #8 am: 02. Februar 2008, 18:28:13 »
debian:~# cat /proc/sys/kernel/random/entropy_avail
3167
debian:~# hexdump /dev/random
..... <Strg+C>
debian:~# cat /proc/sys/kernel/random/entropy_avail
67
debian:~# hexdump /dev/random
<nu kommt nix mehr>
Toktar
--
Jawoll!
Und DNS braucht's nicht, das ist was fuer Weicheier, die sich keine Zahlen merken koennen.
[Karlheinz Boehme in dcsf]

Offline escimo

  • Sobl Guru
  • *****
  • Beiträge: 1674
  • SPARCstation 2
    • Youtube-Kanal opensparcbox.org
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #9 am: 03. Februar 2008, 16:40:17 »
1 /* File myrandom.c */
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <sys/times.h>
 5
 6 int main(int argc,char **argv)
 7 {
 8      unsigned char sds[]={13,17,19,23,29};
 9      int i,j,s,v;
10     struct tms dummy;
11     if(argc>1) i=atoi(argv[1]);
12     while(argc<2 || i--)
13     {
14         s=s*sds[4];
15         v=times(&dummy);
16         for(j=0;j<4;j++) s+=sds[j]*(v>>(8*j));
17         putchar(s);
18     }
19     return 0;
20 }
Hat mich jetzt gerade mal 15 Minuten gekostet.
Ich hätte nicht gedacht, dass nur 20 Zeilen Quellcode nötig wären. Man merkt, ich bin mit der Materie nicht wirklich vertraut. Zu dieser Thematik muss ich mich bei Gelegenheit kundig machen. :-\

Mal sehen, ob ich das zusammenbekomme:
L1: Kommentar
L2-4: Einbindung benötigter Header
L6: Definition Funktion main()
L7: Block-Beginn Funktion main()
L8: Definition sds[]-Array für Zeichen (standard deviations of generated variables?) - in diesem Fall Steuerzeichen (numerische Bedeutung: Primzahlen)
     13 = 'CR' (Carriage Return)
     17 = 'DC1' (Device Control 1)
     19 = 'DC3' (~ 3)
     23 = 'ETB' (End of Transmission Block)
     29 = 'GS' (Group Separator)
L9: Deklaration von Integer-Variablen "i", "j" (Zähler) und "s" (Symbol?) sowie "v" (Zeit vergangen?)
L10: Deklaration Struktur tms mit Namen "dummy"
L11: Parameter angegeben? Wenn ja, Umwandlung des ersten Parameters von ASCII nach Integer und Speichern mit Variable "i"
L12: Kopf der Schleife;
L13: Block-Beginn der Schleife
L14-L16: Erzeugung des zufälligen Zeichens  mit Multiplikation, Addition und Right-Shifting und einer inneren Schleife (L16 ???)
L17: "s" wird auf die Standardausgabe geschrieben
L18: Block-Ende der Schleife
L19: Verlassen der Funktion main() mit Rückgabewert "0"
L20: Block-Ende Funktion main()

$> dd bs=512 count=2000 if=myrandom of=randomfile
14+1 records in
14+1 records out
$> ls -l randomfile
-rw-r--r--   1 sx users     7416 Feb   3 17:13 randomfile
$> myrandom 1000 > randomfile2
$> ls -l randomfile2
-rw-r--r--   1 sx users     142577 Feb   3 17:13 randomfile2

Hätte in Zeile 13 "while (i--)" nicht gereicht oder wolltest du dir den Test auf "(argc<2) ? a:b" sparen?
Was passiert auf Zeile (Line) 16 im Detail, Martin? Kannst du das dem escimo erklären?  ::)

Grüße
Stephan
« Letzte Änderung: 03. Februar 2008, 16:47:03 von escimo »

sonnenblen.de - Das unabhängige Sun User Forum

Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #9 am: 03. Februar 2008, 16:40:17 »

mdjr

  • Gast
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #10 am: 03. Februar 2008, 22:52:20 »
L8: Definition sds[]-Array für Zeichen (standard deviations of generated variables?) - in diesem Fall Steuerzeichen (numerische Bedeutung: Primzahlen)
L14-L16: Erzeugung des zufälligen Zeichens  mit Multiplikation, Addition und Right-Shifting und einer inneren Schleife (L16 ???)
Was passiert auf Zeile (Line) 16 im Detail, Martin? Kannst du das dem escimo erklären?  ::)
Hier habe ich an "SeeDS" gedacht. Hier einfach Primzahlen - die eignen sich besonders dafür. Sie sollen in Zeile 16 dafür sorgen, dass jedes Byte der Zeit aus "times()" auch irgendwie ins untere Byte von "s" hineinkommt, da sonst ja nur das untere Byte von "times()" verwendet werden würde.
Schließlich wird nur das untere Byte von "s" geschrieben; die höheren Bytes von "s" kommen niemals nach unten. Da auch die oberen Bytes von "times()" mehr oder weniger "zufällig" sind, werden sie in Zeile 16 nach unten kopiert.

$> myrandom 1000 > randomfile2
$> ls -l randomfile2
-rw-r--r--   1 sx users     142577 Feb   3 17:13 randomfile2
Das wundert mich jetzt aber. Bei mir war die Datei genau so groß wie das Argument (also bei "myrandom 1000" war die Datei 1000 Bytes lang).

Hätte in Zeile 13 "while (i--)" nicht gereicht oder wolltest du dir den Test auf "(argc<2) ? a:b" sparen?
Das ganze funktioniert so:
Fall: Keine Argumente angegeben: argc ist 1 => Endlosschleife; eignet sich für "myrandom | dd bs=1 count=1000 > outfile"
Fall: Argumente angegeben: argc>1 => Schleife läuft i mal durch

Grüße
Martin

Offline escimo

  • Sobl Guru
  • *****
  • Beiträge: 1674
  • SPARCstation 2
    • Youtube-Kanal opensparcbox.org
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #11 am: 04. Februar 2008, 16:23:49 »
Hier habe ich an "SeeDS" gedacht. Hier einfach Primzahlen - die eignen sich besonders dafür. Sie sollen in Zeile 16 dafür sorgen, dass jedes Byte der Zeit aus "times()" auch irgendwie ins untere Byte von "s" hineinkommt, da sonst ja nur das untere Byte von "times()" verwendet werden würde.
Schließlich wird nur das untere Byte von "s" geschrieben; die höheren Bytes von "s" kommen niemals nach unten. Da auch die oberen Bytes von "times()" mehr oder weniger "zufällig" sind, werden sie in Zeile 16 nach unten kopiert.
Ich kann dir zwar "noch" nicht folgen aber mit der Zeit steige ich bestimmt dahinter. :-\

Das ganze funktioniert so:
Fall: Keine Argumente angegeben: argc ist 1 => Endlosschleife; eignet sich für "myrandom | dd bs=1 count=1000 > outfile"
Fall: Argumente angegeben: argc>1 => Schleife läuft i mal durch
Oha, in Ordnung. Das habe ich jetzt. Nächstes Wochenende Poste ich mal einen erweiterten Output dieses Programms. Vielen Dank Martin.

@Toktar: user@host:~ $ cat /proc/sys/kernel/random/entropy_avail
3712
user@host:~ $ dd bs=512 count=4 if=/dev/random of=randomfile
0+4 records in
0+4 records out
user@host:~ $ ls -l randomfile
-rw-r--r--  1 user users 342 2008-02-04 16:12 randomfile
user@host:~ $ cat /proc/sys/kernel/random/entropy_avail
3604
Das geht wieder "was" verloren und Entropy-Informationen sollten genügend vorliegen. ???

Grüße
Stephan

Offline Toktar

  • Sobl Master
  • ****
  • Beiträge: 333
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #12 am: 04. Februar 2008, 18:38:52 »
Shell 1

simon:/home# cat /etc/debian_version
4.0
simon:/home# uname -a
Linux simon 2.6.18-4-686 #1 SMP Wed May 9 23:03:12 UTC 2007 i686 GNU/Linux
simon:/home# dd bs=512 count=4 if=/dev/random of=randomfile
0+4 Datensätze ein
0+4 Datensätze aus
93 Bytes (93 B) kopiert, 75,1021 Sekunden, 0,0 kB/s
simon:/home# ls -ltrh
-rw-r--r-- 1 root   root           93 2008-02-04 18:11 randomfile
simon:/home#

Shell 2 (parallel zum dd)

simon:~# cat /proc/sys/kernel/random/entropy_avail
40
simon:~# cat /proc/sys/kernel/random/entropy_avail
40
simon:~# cat /proc/sys/kernel/random/entropy_avail
63
simon:~# cat /proc/sys/kernel/random/entropy_avail
63
simon:~# cat /proc/sys/kernel/random/entropy_avail
2
simon:~# cat /proc/sys/kernel/random/entropy_avail
72
simon:~# cat /proc/sys/kernel/random/entropy_avail
129

Die entrophy_avail erholt sich auf meiner Kiste auch nicht so schnell. Nach einer halben Stunden und Grundreinigung meiner 5jährigenTochter ist sie nun auf 450 gestiegen.
« Letzte Änderung: 04. Februar 2008, 18:53:25 von Toktar »
Toktar
--
Jawoll!
Und DNS braucht's nicht, das ist was fuer Weicheier, die sich keine Zahlen merken koennen.
[Karlheinz Boehme in dcsf]

Offline escimo

  • Sobl Guru
  • *****
  • Beiträge: 1674
  • SPARCstation 2
    • Youtube-Kanal opensparcbox.org
Re: Erzeugung einer Binärdatei fester Größe mittels Kommando dd
« Antwort #13 am: 17. Februar 2008, 19:22:25 »
...Nächstes Wochenende Poste ich mal einen erweiterten Output dieses Programms.
Da gerade eine Tip-Verbindung von der SS20 zur U80 aktiv ist, habe ich die Gelegenheit genutzt, den erweiterten Output noch wie angekündigt bereitzustellen.

Code: (c) [Auswählen]
/* file by mdjr */
#include <stdio.h>
#include <stdlib.h>
#include <sys/times.h>

int main( int argc, char **argv )
{
unsigned char sds[] = {13,17,19,23,29};
int i, j, s, v;
struct tms dummy;
int c = 1; //counter
int sc = 0; //cache for variable 's'
if (argc>1) i = atoi( argv[1] );

while (argc<2 || i-- ) {
// while (i--) {
printf("Durchlauf %d:",c++);
s = s * sds[4];
printf(" s_davor=%d,",s);
v = times( &dummy );
printf(" v=%d,",v);
for (j=0; j<4; j++) {
s += sds[j] * (v >> (8*j));
sc = s;
printf("\n\t %d = %d + %d * (%d >> (8 * %d))",s,sc,sds[j],v,j);
}
printf("\n");
putchar(s);
if (argc<2 || i) printf("Repeat loop: true\n",i);
else printf("Repeat loop: false\n",i);
}
return 0;
}

Gruß
escimo
« Letzte Änderung: 17. Februar 2008, 19:25:33 von escimo »