Informationen von stat und statfs ausgeben
-
Hallo,
ich wueder gerne die Informationen, die ich in stat() und statfs() erhalten habe, ausgeben lassen. Jedoch weiss ich nicht, welchen format-type ich bei printf angeben muss, ohne warnings zu erhalten.
Ich habe bisher:
printf("ID of device containing file: %d\n" "Inode number: %d\nProtection: %s\n" "Number of hard links: %d\nUser-ID of owner: %d\n" "group ID of owner: %d\ndevice ID: %d\n" "total size: %d\nblocksize: %d\n" "numer of blocks allocated: %d\n", buf->st_dev, buf->st_ino, buf->st_mode, buf->st_nlink, buf->st_uid, buf->st_gid, buf->st_rdev, buf->st_size, buf->st_blksize, buf->st_blocks);
Die Warnings sehen so aus:
stats.c: In function ‘print_stat’: stats.c:54:4: warning: format ‘%d’ expects type ‘int’, but argument 4 has type ‘__dev_t’ stats.c:54:4: warning: format ‘%d’ expects type ‘int’, but argument 5 has type ‘__ino64_t’ stats.c:54:4: warning: format ‘%s’ expects type ‘char *’, but argument 6 has type ‘__mode_t’ stats.c:54:4: warning: format ‘%d’ expects type ‘int’, but argument 10 has type ‘__dev_t’ stats.c:54:4: warning: format ‘%d’ expects type ‘int’, but argument 11 has type ‘__off64_t’ stats.c:54:4: warning: format ‘%d’ expects type ‘int’, but argument 12 has type ‘__blksize_t’ stats.c:54:4: warning: format ‘%d’ expects type ‘int’, but argument 13 has type ‘__blkcnt64_t’
Welchen Typ muss ich denn dort angeben?
Das Gleiche gilt uebrigens auch fuer statfs.Vielen Dank
-
stats.c:54:4: warning: format ‘%s’ expects [b]type ‘char *’[/b], but argument 6 has type ‘__mode_t’
Die Anleitung zu sys/types.h hast du aber schon einmal gelesen, oder?
Bevor du weiter Ratespielchen betreibst: In sys/types.h steht, dass das allesamt arithmetische Typen sind, weiter steht dort auch, welche davon signed und welche unsigned sind. Da du mit ziemlicher Sicherheit den gcc benutzt, kannst du C99 benutzen um die alle zu intmax_t bzw. size_t zu casten und dann mittels %j bzw. %z auszugeben. Zwar mag es in 99.99 % der Fälle auch leichter gehen, aber so funktioniert das auch auf jeder noch so exotischen (oder zukünftigen) Maschine.
-
Oh, entschuldigung, hatte es zuerst mit char* gemacht, aber dann weiterhin alle in %d geaendert gehabt, nur noch nicht editiert.
Ich soll also <inttypes.h> inkludieren (fuer den type intmax_t) und nach "intmax_t" casten, soweit richtig?
D.h. quasi:
printf("%j\n", (intmax_t) buf->st_dev)
usw?
Da erhalte ich
stats.c:58:2: warning: unknown conversion type character 0xa in format stats.c:58:2: warning: too many arguments for format
Und woher weiss ich, ob ich nach intmax_t oder size_t casten muss oder ist das egal?
-
printf("%jd\n", (intmax_t) foo);
War schlecht ausgedrückt. Das z bzw. j sind Größenangaben.
Der Unterschied zwischen size_t und intmax_t ist das Vorzeichen. Aber wenn ich genauer darüber nachdenke, ist es wohl besser, uintmax_t zu nehmen, da nicht garantiert ist, dass size_t der größte vorzeichenlose Integer ist.
-
Sehr gut, funktioniert soweit alles
Habe jetzt zu den Permissions eine Methode geschrieben, die aus dem Zahlenwert einen String macht, der so aussieht, wie die lesbaren permissions (drwx-w---x usw.), da klappt jedoch etwas nicht.
Ich habe meine print_stat-Methode erweitert:
void print_stat(char *dest, const char* filename, struct stat* buf) { char *perm="----------"; read_permissions((uintmax_t) buf->st_mode, perm); sprintf(dest,"Filename: %s\nID of device containing file: %ju\n" "Inode number: %ju\nProtection: %s\n" "Number of hard links: %ju\nUser-ID of owner: %ju\n" "group ID of owner: %ju\ndevice ID: %ju\n" "total size: %ju\nblocksize: %ju\n" "number of blocks allocated: %ju\n", filename, (uintmax_t) buf->st_dev, (uintmax_t) buf->st_ino, perm, (uintmax_t) buf->st_nlink, (uintmax_t) buf->st_uid, (uintmax_t) buf->st_gid, (uintmax_t) buf->st_rdev, (uintmax_t) buf->st_size, (uintmax_t) buf->st_blksize, (uintmax_t) buf->st_blocks); }
Meine read_permissions-Methode sieht so aus (ich weiß, geht bestimmt viel einfacher, aber das war mal hier eine kleine Aufgabe):
void read_permissions(uintmax_t mode, char* string){ if(S_IFDIR & mode) string[0]='d'; if(S_IRUSR & mode) string[1]='r'; if(S_IWUSR & mode) string[2]='w'; if(S_IXUSR & mode) string[3]='x'; if(S_IRGRP & mode) string[4]='r'; if(S_IWGRP & mode) string[5]='w'; if(S_IXGRP & mode) string[6]='x'; if(S_IROTH & mode) string[7]='r'; if(S_IWOTH & mode) string[8]='w'; if(S_IXOTH & mode) string[9]='x'; }
Somit sollte doch nach dem Aufruf der perm-String geändert worden sein, oder nicht?
Bei mir kommt aber einfach gar keine Ausgabe mehr, wenn ich dest ausgeben lasse...
-
Mach daraus mal
char perm[]="----------";
-
Ah, so funktioniert es und hatte es in der Aufgabe auch so gelöst...
Danke
-
Fabulus schrieb:
Ah, so funktioniert es und hatte es in der Aufgabe auch so gelöst...
DankeVerstehst du denn auch den Unterschied? Falls nicht, schnapp dir mal ein gutes C Buch.
-
Ich könnte es nicht richtig erklären.
Mit char* fordert man Platz für einen Zeiger an (welcher auf jede Adresse im Speicher liegen kann) und char[10] fordert Platz für ein char-Array der Länge 10 an, dessen Adresse aber nicht mehr später verändert werden kann (außer natürich auf die Adressen der Elemente). So in etwa?
-
Jain.
char * ist ein Zeiger auf char, ja. Wenn du
char * foo = "Beispiel";
machst, dann zeigt foo auf das Zeichenkettenliteral "Beispiel". Dessen Typ ist eigentlichconst char[9]
, d.h. man kann den Text nicht verändern und eigentlich dürfte ein (nicht const) char* da niemals draufzeigen. Ist aber eine Sonderregel in C, dass man das trotzdem darf, Zugeständnis an alten Code. Bei deinem Programm das nicht funktioniert hat, hast du genau dies getan und daher ging das auch schief.
Wenn du statt dem Zeiger jedoch ein Array mit einem Zeichenkettenliteral initialisierst, dann ist das eine besondere Form der Initialisierung, bei der der Inhalt des Literals in das Array kopiert wird. Und da der Inhalt des Arrays (es ist ja selber char[9] und nicht const char[9]) veränderlich ist, funktioniert es damit. Das Weglassen der Größenangabe macht, dass der Compiler für uns die Zeichen zählt, das macht das Literal einfacher änderbar.Beachte jedoch, dass [] und * bei Funktionsargumenten beide die Bedeutung von Zeigern haben.
-
Ah, okay! Das hab ich verstanden! Eine Zeichenkette ist nicht veränderbar, wenn sie mit * definiert wurde, da nur auf die Zeichenkette gezeigt wird. Das wusste ich noch nicht.
Dass Arrays und * beides Zeiger sind, war mir klar, deshalb habe ich beides geichermaßen verwendet.
-
Fabulus schrieb:
Dass Arrays und * beides Zeiger sind, war mir klar, deshalb habe ich beides geichermaßen verwendet.
Normalerweise eben nicht! Nur bei Parameterübergabe an Funktionen steht die Arrayschreibweise für einen Pointer. Dir täte wirklich mal ein gutes C Buch gut.
-
Äh, klar, als Funktionsparameter mein ich doch, wie du vorher schon geschrieben hast. Würde sich ja auch sonst mit dem widersprechen, was ich einen Satz vorher geschrieben habe.
C-Bücher habe ich nicht, nur C++, da ich bis vor kurzem nicht vor hatte, in C zu programmieren, aber dies hat sich wohl geändert. Bisher habe ich sonst zu C alles nur aus dem Netz.
-
In C++ wäre der ganze Thread nach einer Zeile erledigt gewesen, aber das ist dir sicherlich klar (wenn nicht jetzt, dann wenn du mehr gelernt hast).
-
SeppJ schrieb:
In C++ wäre der ganze Thread nach einer Zeile erledigt gewesen
ja nee is klar
-
DrGreenthumb schrieb:
SeppJ schrieb:
In C++ wäre der ganze Thread nach einer Zeile erledigt gewesen
ja nee is klar
Ich verstehe nicht. Oder meinst du, dass die Frage gar nicht erst aufgekommen wäre? Ja, das wäre wohl so.
-
nee, ich meine, wieso sollte C++ hier hilfreich sein. Die String-Literale sind dort genauso wie in C. Und um irgendwelche C-Typen aus Linux-Headern *richtig* auszugeben, muss man auch in C++ den Typ kennen.