Ungepuffertes Schreiben in eine Datei

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Ungepuffertes Schreiben in eine Datei

Beitrag von Columbus » 07.05.2006 20:06:39

Hallo zusammen,
ich habe ein kleines aber widerspänstiges Problem. Und zwar möchte ich eine Funktion anlegen, mit der ich ungepuffert (also mit open, write usw. ) in eine Datei schreiben kann.
Die Funktion bekommt als Parameter den Namen einer anzulegenden Datei und eine einfache Zahl, die in diese Datei zu schreiben ist.

So siehts aus:

Code: Alles auswählen

/* Funktion zum Erzeugen einer Datei, in die die Semaphoren-ID geschrieben wird             */
int erzeuge_datei ( const char * datei_name, int sem_id )
{
  int datei_descriptor = 0;
  char uebergabe_string[3];
  int schluessel = sem_id;

  if ( ( datei_descriptor = open ( datei_name , O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR ) ) == -1 )
  {
      perror ( "Fehler beim Erzeugen der Datei! \n" );
      exit ( errno );
  }

  sprintf ( uebergabe_string, "%d", schluessel );
  /*{
     perror ( "Fehler bei erzeugen eines Strings \n" );
     exit ( errno );
  }*/

  if ( ( write ( datei_descriptor,uebergabe_string , 3 ) ) == -1 )
  {
     perror ( "Fehler beim beschreiben der Datei! \n" );
     exit ( errno );
  }

  close ( datei_descriptor );
  
  return ( 1 );
}
Wenn ich die Funktion aufrufe, erhalte ich die Fehlermeldung: Fehler beim beschreiben der Datei! \n : Bad file descriptor !! :?

Wenn ich die Zeile mit dem sprintf allerdings rausnehme, und die Zahl (sem_id ) direkt in die Datei schreibe, gibt es dieses Problem nicht. Klar daß dann dabei nicht das herauskommt, was man will. In der Datei steht dann ein einfaches kleines 's' was ich auch nicht verstehe ( ach ich sollte noch sagen, daß ich immer eine 42 als Zahl übergebe ). Aber die 42 ist nicht der ASCII-Code für ein kleines 's'.

Weiter ist auch noch zu vermerken, daß die in der Funktion erzeugte Datei nicht mit dieser Funktion gelöscht werden kann:

Code: Alles auswählen

void loesche_datei ( const char * datei_name )
{
   if ( ( remove ( "datei_name" ) ) == -1 )
   {
       perror ( "Fehler beim Loeschen der Datei! \n" );
       exit ( errno );
   }
}
<seufz> was habe ich falsch gemacht, was übersehen </seufz>

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Ungepuffertes Schreiben in eine Datei

Beitrag von gms » 07.05.2006 20:50:34

mir ist jetzt auf die schnelle nur der Fehler beim Löschen aufgefallen. Du solltest die Anführungszeichne von "datei_name" entfernen, das sollte ja der Inputparameter sein
Columbus hat geschrieben:

Code: Alles auswählen

void loesche_datei ( const char * datei_name )
...
   if ( ( remove ( "datei_name" ) ) == -1 )
was wird denn beim Schreiben von errno zurückgeliefert ?

Gruß
gms

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Beitrag von Columbus » 07.05.2006 20:54:50

Sehr gut.
Das Problem mit dem löschen wär schon mal gelöst :D

Vielen Dank

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 07.05.2006 20:56:23

kannst du noch den Wert von errno posten

[edit]
wollte ich zuerst noch anmerken. Wieso setzt du die Länge beim Aufruf der write Funktion auf 3 ?
[/edit]

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Beitrag von Columbus » 07.05.2006 21:04:37

Du meinst das errno, wenn er beim write aussteigt? Das ist ": Bad file descriptor"

Auf 3 habe ich das gesetzt, hmm naja um noch ein bischen Platz für ein 0-Bit zu haben. Faktisch muß aber einfach nur eine Integerzahl in die Datei geschrieben werden. Und Integer verbraucht 2 Byte ?!!
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 07.05.2006 21:07:28

Die meisten Systeme dürften mitlerweile 32 Bit (oder 64 Bit) haben :wink:

Auf einem 32 Bit System:

Code: Alles auswählen

gms@gms1:~$ cat xx.c
#include <stdio.h>
int main() {
  printf("%d\n",sizeof(int));
}
gms@gms1:~$ gcc -o xx xx.c
gms@gms1:~$ ./xx
4

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Beitrag von Columbus » 07.05.2006 21:15:19

Ich habe es mal mit 4 und 5 probiert, hat aber nicht geholfen. Ich bekomme immer noch den Fehler "bad file descriptor"!

Also dabei habe ich dem Puffer ( uebergabe_string )eine größe von 5 gegeben und in der write-Funktion die Länge '6' .
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 07.05.2006 21:19:57

wenn der uebergabe_string 5 Bytes lang ist solltest du in der write Funktion auch maximal 5 Bytes angeben, sonst wird über den Buffer hinausgelesen und durch das sprintf(...,"%d") erhälst du wahrscheinlich einen Bufferoverflow da wird ja die Zahl in eine Zeichnenkette konvertiert und kann daher auch Länger als 5 Byte lang werden. Welche Zahl hast du denn zum Testen herangezogen ?

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Beitrag von Columbus » 07.05.2006 21:23:57

Ok, habe ich gemacht. Das wars aber nicht, denn er wirft immer noch diese Fehlermeldung "Bad file descriptor" :?
Komisch!

Also, das ganze sieht jetzt so aus:

Code: Alles auswählen

int erzeuge_datei ( const char * datei_name, int sem_id )
{
  int datei_descriptor = 0;
  char uebergabe_string[5];
  int schluessel = sem_id;

  if ( ( datei_descriptor = open ( datei_name , O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR ) ) == -1 )
  {
      perror ( "Fehler beim Erzeugen der Datei! \n" );
      exit ( errno );
  }

  sprintf ( uebergabe_string, "%d", schluessel );
  /*{
     perror ( "Fehler bei erzeugen eines Strings \n" );
     exit ( errno );
  }*/

  if ( ( write ( datei_descriptor, uebergabe_string , 5 ) ) == -1 )
  {
     perror ( "Fehler beim Beschreiben der Datei! \n" );
     exit ( errno );
  }

  close ( datei_descriptor );
  
  return ( 1 );
}
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 07.05.2006 21:30:24

Du solltest für den Buffer auf einem 32 Bit System mindestens 12 Byte reservieren:

Code: Alles auswählen

gms@gms1:~$ cat xx.c
#include <stdio.h>
#include <limits.h>
int main() {
  int n=INT_MAX;
  printf("%d\n",n);
  n=INT_MIN;
  printf("%d\n",n);
}
gms@gms1:~$ gcc -o xx xx.c
gms@gms1:~$ ./xx
2147483647
-2147483648
Beachte die Länge der Ausgabe

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Beitrag von Columbus » 07.05.2006 21:38:48

STRIKE!!! 8) 8) 8)

Damit gehts. Also auf solche Sachen wäre ich jetzt nicht gekommen. fopen und fprintf sind doch sehr viel geduldiger, bequemer und vergeben auch viel mehr oder?
Aber man muß halt auch mal was neues Probieren. :)

Vielen Dank auf jeden Fall !!!

Gruss Christian

Oh, einen kleinen Wehmutstropen habe ich noch: in der Datei steht jetzt ein '65536tZ' statt eine '42'. Aber ich denke das grieg ich hinn.
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

Antworten