[C] droits d'accès sur un fichier

droits d'accès sur un fichier [C] - C - Programmation

Marsh Posté le 18-10-2004 à 21:45:03    

Bonjour ,  
 
J'aimerais pouvoir récupérer les droits d'accès à un fichier pour le propriétaire et le groupe du propriétaire.
Pour cela j'utilise la fonction access().
 
Je sais qu'access teste si le processus est autorisé à lire, écrire ou éxécuter sur ce fichier et je sais également comment récupérer l'id du propriétaire et du groupe du propriétaire grâce aux fonctions getuid() et getgid().
 
Cependant, je ne vois pas comment utiliser le test access(fichier,mode) pour le propriétaire puis pour le groupe. Je sais qu'il faut surement faire quelque chose avec getuid et getgid mais je ne vois pas quoi les manipuler.
 
Pourriez m'expliquer comment les manipuler pour pouvoir utiliser le access pour le propriétaire puis pour le groupe ?
 
 
Merci d'avance.
 

Reply

Marsh Posté le 18-10-2004 à 21:45:03   

Reply

Marsh Posté le 18-10-2004 à 22:14:31    

t'es sous unix ?
 
y a moyen avec la suite de 'bytes' que te renvoie la fonction pour tester les droits, que tu peut transformer 'facilement' en truc du style rw-rw-rw-  ;)  
 


---------------
.
Reply

Marsh Posté le 18-10-2004 à 22:37:19    

C'est bon j'ai trouvé dans access je fais un décalage de bits sur le mode.
Vu que le mode est géré par 9 bitset que access prend en compte les 3 premiers,  je décale de 3 bits à gauche  pour voir le groupe du propriétaire.
 

Reply

Marsh Posté le 18-10-2004 à 22:52:29    

t'ennuie pas avec tout. utilise la notation octale
 
0755
 

Reply

Marsh Posté le 18-10-2004 à 22:59:25    

man stat ?


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 18-10-2004 à 23:04:56    

je viens de voir que dans st_mode, on avait les droits stockés sur 9 bits effectivement merci.

Reply

Marsh Posté le 18-10-2004 à 23:24:05    

ouaip donc un simple
 
(buf.st_mode & 0777) == mode :sol:

Reply

Marsh Posté le 18-10-2004 à 23:25:16    

En fait, je dois pouvoir tester si l'utilisateur ou le groupe peuvent lire, écrire ou éxécuter (le mode est passé en paramètre) le fichier passé en paramètre.
 
Le problème c'est que je vois pas comment comparer ce qui est stocké sur 9 bits dans st_mode avec les différents droits de lecture, écriture ou éxécution.

Reply

Marsh Posté le 18-10-2004 à 23:55:48    

Là j'ai essayé de faire ça :
 
- pour la lecture pour le propriétaire :  mode=0400;  
 
 et je compare ce mode comme dit précédemment : (buf.st_mode & 0777)==mode
 
Le problème c'est que si l'user a un droit en plus de celui du droit de lecture, ça ne marchera pas, idem si le groupe ou les autres ont des droits.
Comment définir mode de façon à ce que ça marche, c'est à dire que ça me vérifie que c'est bien en mode lecture dans ce cas là quelque soit les droits d'écriture et d"éxécution pour le propriétaire et les droits pour le groupe et les autres ?

Reply

Marsh Posté le 19-10-2004 à 00:34:26    

à toi de jouer avec &
 
 
tu as passé tout le topic à tourner autout des droits. Les droits rwx, c'est juste 9 bits. Alors manipule les comme des bits. Tu veux savoir si un bit est à 1 ? fait un & avec le masque qu'il faut

Reply

Marsh Posté le 19-10-2004 à 00:34:26   

Reply

Marsh Posté le 19-10-2004 à 01:29:56    

Merci, j'y suis arrivé finalement :)
 
Le truc c'est que je suis pas trop habitué à manipuler les bits donc je voyais pas l'idée à mettre en oeuvre alors que c'était tout simple.

Reply

Marsh Posté le 19-10-2004 à 19:39:04    

sylsau a écrit :

je viens de voir que dans st_mode, on avait les droits stockés sur 9 bits effectivement merci.


Petite erreur, les droits sont stockés sur 12 bits car il y a aussi les bits spéciaux "sst"
 
De plus, si tu veux vraiment être propre, tu dois utiliser les constantes "S_IRUSR", "S_IWUSR", "S_IXUSR", "S_IRGRP", "S_IWGRP", "S_IXGRP", "S_IROTH", "S_IWOTH" et "S_IXOTH"
Tu remarqueras que ces constantes ont un nom approprié "S_IWGRP" <=> "is write for group" etc.
D'autres constantes regroupent les premières pour plus de facilité: "S_IRWXU", "S_IRWXG" et "S_IRWXO"
 

sylsau a écrit :

En fait, je dois pouvoir tester si l'utilisateur ou le groupe peuvent lire, écrire ou éxécuter (le mode est passé en paramètre) le fichier passé en paramètre.


 
=> if ((mode & (S_IRWXU | S_IRWXG)) != 0)


Message édité par Sve@r le 19-10-2004 à 19:41:14
Reply

Marsh Posté le 19-10-2004 à 20:46:26    

Tout d'abord comment ces constantes sont initialiées pour un fichier donné ?
 
et les droits sont stockés comment dans ces constantes ?
par exemple si l'utilisateur a le droit de lecture sur le fichier , dans la constante S_IRUSR y aura 1 et 0 sinon ?

Reply

Marsh Posté le 20-10-2004 à 09:16:31    

j en profite pour poser ma quesiton qui doit surement etre lie
 
Read a file from standard input line by line. If a line is less than 70 characters, add spaces to make it 70 characters. If it is longer than 70 characters, take the first 70 characters. Make sure your program won't break if the user types in a long line. Even if the line is arbitrarily long! (So, if you think of a maximum line size, imagine the user types a line that is longer than that - will your program still work?)
 
Write each line out to a file called filestore. If filestore exists, you should add the new lines to the end of it, otherwise create it from scratch and make sure that only the current user can access it. Each line should be written to filestore as 70 characters followed by a newline character. When you reach the end of file on standard input, your program should exit.

on ne doit utiliser que du low leve i/o
 

Code :
  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #define MAX 10
  4. int main()
  5. {
  6.     int my_file_descriptor;
  7.     int input_char;
  8.     int counter=0;
  9.     char my_write_str[MAX+1]; //last char is a new line char
  10.     while ((input_char = getchar()) != EOF)
  11.     {
  12.         if (counter < MAX)  my_write_str[counter] = input_char;
  13.         counter ++;
  14.    
  15.         if (input_char == '\n')
  16.         { 
  17.             if (counter < MAX)
  18.             {
  19.                 int space_needed = MAX-counter+1;
  20.                  //the last char was a /n have to be rpalce by a space
  21.                 counter --;
  22.                 int i;
  23.            
  24.                 for(i=0; i<space_needed; i++)
  25.                 {
  26.                     my_write_str[counter+i]=' ';
  27.                 }
  28.             }
  29.             my_write_str[MAX]='\n';
  30.             my_file_descriptor = open ("filestore", O_RDWR | O_CREAT | O_APPEND);
  31.             write (my_file_descriptor, (void *) my_write_str, MAX+1);
  32.             counter = 0;
  33.             fsync (my_file_descriptor); //ensure it is written  
  34.             close (my_file_descriptor);
  35.         }
  36.     }
  37.     return 0;
  38. }


 
il y atil quelque chose de particulier a ajoute ?

Reply

Marsh Posté le 20-10-2004 à 10:01:23    

utilise fgets et les FILE*
 
utilise getline si tu en disposes.

Reply

Marsh Posté le 20-10-2004 à 10:06:34    

getline ça s'éloigne un peu du low level I/O non ?


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 20-10-2004 à 10:20:11    

tiens j'avais pas vu ça dans l'énoncé :o
cela dit, s'il faut faire bas niveau, faut pas non plus utilisé getchar

Reply

Marsh Posté le 20-10-2004 à 21:39:58    

sylsau a écrit :

Tout d'abord comment ces constantes sont initialiées pour un fichier donné ?
 
et les droits sont stockés comment dans ces constantes ?
par exemple si l'utilisateur a le droit de lecture sur le fichier , dans la constante S_IRUSR y aura 1 et 0 sinon ?


Tu n'as pas bien compris comment on se sert de ces constantes.
Tout d'abord, une constante est... constante donc elle ne varie pas au grè des situations.
Ici, elles servent à filtrer les bits qui t'intéressent issus des droits.
Essaye d'imaginer que dans les droits, chaque lettre "rwxrwxrwx" correspond à un bit à "1" ou à "0" suivant que le droit y est ou n'y est pas.
Donc tu ne connais pas les droits de ton fichier. Ils sont à ton niveau comme cela:  
????????? (on laisse tomber les droits spéciaux "sst" qui n"apportent rien de plus au raisonnement)
 
Tout d'abord il te faut récupérer quelle est la valeur de ces droits. Mais dans un fichier Unix, les droits font partie d'un ensemble appelé "état" (qui contient aussi la taille, le propriétaire, les dates de modif, etc...) et cet état peut être récupéré dans une variable de type "struct stat" (ce type est défini dans le header "<sys/stat.h>" ). Donc tu as besoin d'une variable de type "struct stat"
=> struct stat toto;
 
Ensuite, il te faut remplir cette variable. le remplissage se fait avec la fonction "stat" => stat("nom_du_fichier", &toto);
 
Enfin tu peux accéder aux droits du fichier "nom_du_fichier" qui sont stockés dans "toto.st_mode"
 
Maintenant si tu veux savoir si le premier "r" y est ou n'y est pas, il te suffit de filtrer par un "&" cette variable "toto.st_mode" avec la valeur binaire "100000000" (=> 0400 en octal). Le premier bit sortira inchangé de ce filtre et les autres sortiront à 0
  ?????????
& 100000000
= ?00000000
 
Si cette opération te donne "1", c'est que le premier bit vaut 1 donc que le premier droit "r" est là. Sinon il vaut 0.
 
Si maintenant tu veux vérifier que certains droits y sont tous, il te suffit de combiner ces droits avec un "|" et d'utiliser le résultat pour filtrer la variable "toto.st_mode". Si le résultat est identique au filtre, c'est que tous les droits recherchés y sont. Sinon, il en manque au-moins un. Et si le résultat vaut "0", c'est qu'aucun des droits que tu cherches n'est présent dans "toto.st_mode".
 
Dernier truc: Tu peux utiliser les valeurs octales comme filtre ou utilier les macrodéfinitions "S_Iqqchose". L'avantage de cette seconde méthode est que si, un jour, dans un lointain futur, Unix voit apparaître de nouveaux droits et une autre façon de les coder, les macrodéfinitions suivront le changement et tu n'auras rien d'autre à faire que recompiler ton programme. Si, au contraire, tu utilises les nombres littéraux "0400", "0200", etc, et que ces nombres changent demain, tu devras reprendre tout ton code pour le faire évoluer.
 
Dans ton premier topic, tu cherches à savoir si l'un des droits "rwx" est présent pour le propriétaire ou le groupe, cela te donne
=> if ((toto.st_mode & (S_IRWXU | S_IRWXG)) != 0)
 
Pour le reste, "man stat" pour plus de détails...


Message édité par Sve@r le 20-10-2004 à 21:45:28
Reply

Marsh Posté le 20-10-2004 à 22:25:04    

ouais c'est bon cette fois je pense que j'ai définitivement compris :)  
Merci à toi  :jap:

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed