Diskussion Datei in Linux erzeugen - Codereview

Mat

Mitglied
Hier der erste Teil aus der Gammelcode-Serie, ganz kurz und knapp, in Anlehnung an:

Damit ich nicht immer nur Java poste, mal eine alte C-Uniaufgabe (abgeändert).

Meine ersten Gedanken, wenn ich das nach der langen Zeit so sehe, habe ich kommentiert und hervorgehoben:
C:
/*
* Aufgabe war:
* 1. Dateinamen als Usereingabe entgegennehmen
* 2. Leere Datei unter angegebenem Namen anlegen und nur mit Owner-Rechten
* 3. Sinnvolle Fehler- und Erfolgsmeldungen ausgeben
*
* Folgende Funktionen mussten genutzt werden:
* fgets, creat, close, printf
*/

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

#define USER_PERMISSION 0700
#define FILENAME_MAX_LENGTH 10

int main() {
  char filename[FILENAME_MAX_LENGTH];
  int resultCode = -1;
  FILE *fp;

  printf("Dateiname:");
  fgets(filename, FILENAME_MAX_LENGTH, stdin);

  // was ist, wenn man 11 Zeichen eingibt,
  // wird das letzte mit \0 überschrieben?
  for (int i = 0; i < FILENAME_MAX_LENGTH; i++) {
    if (filename[i] == '\n') {
      filename[i] = '\0';
      break;
    }
  }

  resultCode = creat(filename, USER_PERMISSION);

  if (resultCode == -1) { // ich glaube, creat hat Konstanten dafür
    printf("FEHLER");     // sehr aussagekräftig
  } else {
    printf("%s erfolgreich erzeugt", filename);
  }

  fp = fopen(filename, "r");
  if (fp == NULL) {
    printf("FEHLER"); // achso
  }
  fclose(fp); // close auch wenn NULL?

  return 0; // immer EXIT_SUCCESS?
}
Bin schon wieder etwas raus aus C, habt ihr noch weitere Überlegungen zum Code?

Edit: Markierte Zeilen waren verrutscht
 
Zuletzt bearbeitet:

german

Aktives Mitglied
devCommunity-Experte
// was ist, wenn man 11 Zeichen eingibt,
Das ist bereits die falsche Frage. fgets liest das '\n' mit und Strings sind nullterminiert. Frage wäre also, was passiert wenn man mehr als 8 Zeichen eingibt? Die gute Nachricht ist, dass fgets immer die Nullterminierung setzt. Damit hast du schon mal eine Fehlerquelle weniger. Eingaben die als letztes Zeichen vor der Nullterminierung kein '\n' enthalten, könntest du als suspekt betrachten und dem User einen Fehler melden, dass er nicht mehr als 8 Zeichen eingeben soll. Alles was nicht mehr in den Puffer passt (also auch das '\n' bei einer Eingabe von 9 Zeichen) bleibt im stdin stehen. (Stichwort Essensreste ;))

// ich glaube, creat hat Konstanten dafür
Hmm, ist POSIX und kein Standard C. Laut Manpage ist die Prüfung auf -1 OK. Zusätzlich wird errno gesetzt. Dafür gibt es dann "sprechende" Macros.
Da ich mit POSIX nicht vertraut bin, bin ich mir nicht sicher ob du ein close hättest ausführen müssen, wenn du einen validen File Descriptor zurück bekommst.

// close auch wenn NULL?
Nein. Undefiniertes Verhalten.
BTW Durftest du fopen eigentlich verwenden?

// immer EXIT_SUCCESS?
Ich hasse Kommandozeilenprogramme die keinen aussagekräftigen Returncode zurückgeben ;) Wenn ich Scripts schreibe, prüfe ich regelmäßig darauf. Ist einfacher und billiger als die Fehlermeldung einzufangen und einen Stringvergleich auszuführen. Und ... wenn du einen Fehler reportest, dann beende das Programm an der Stelle auch gleich.
 
  • Like
Reaktionen: Mat

Mat

Mitglied
Das ist bereits die falsche Frage. fgets liest das '\n' mit und Strings sind nullterminiert.
Achja, ganz vergessen, dass 0x00 noch mit zur Länge zählt. Aber man könnte fast meinen, dass ich das beim Schreiben des Codes noch wusste, weil die Zahl 8 für maximale Dateinamenlängen (+ ".txt") irgendwie an DOS erinnert. Wobei, nein, ich glaube so weit war das nicht gedacht.. das war nur 10, weil ich 10 Finger hab. :D

BTW Durftest du fopen eigentlich verwenden?
Also wenn ich die Beschreibung in der PDF so sehe, war das nicht erforderlich. War wohl Eigeninitiative damals ^^. Aber eigentlich unnötig, weil creat schon vorher einen Fehler geliefert hätte. Ich hätte eher prüfen können, wie man Berechtigungen ausliest (nur um die Lib besser kennenzulernen). Ich sehe auch auf https://linux.die.net/man/2/creat , dass es extra eine Konstante für Owner gibt: S_IRWXU
Außerdem ist wohl das, was ich "resultCode" genannt hab, eigentlich ein filedescriptor, was wiederum eine Art ID ist, die auf die Datei zeigt. Da hätte ich gar nicht mit dem Dateinamen weiterarbeiten müssen, glaube ich.

Und ... wenn du einen Fehler reportest, dann beende das Programm an der Stelle auch gleich.
Stimmt
 

german

Aktives Mitglied
devCommunity-Experte
die Zahl 8 für maximale Dateinamenlängen
Ja, nannte sich "8.3".

war nur 10, weil ich 10 Finger hab. :D
Hehe, ja das ist der einzig plausible Grund. Ich verwette meine grauen Haare, dass du Speicher verschenkst, das wegen Alignment zusätzlich vom Stack reserviert wird. Auch wenn in keinem C-Standard irgendwas über implementationsspezifische Details zu finden sein wird, ist alles was nicht ein Vielfaches der Registerbreite ist, sowieso eher "unnatürlich".

Aber eigentlich unnötig, weil creat schon vorher einen Fehler geliefert hätte.
Japp, eben jenes -1.

Da hätte ich gar nicht mit dem Dateinamen weiterarbeiten müssen, glaube ich.
Genau. Solange du mit den POSIX Funktionen weiter arbeitest, versteht sich. Die C Standardfunktionen können mit dem File Descriptor nichts anfangen.
 
Oben Unten