Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Free Pascal Discussion :

[Linux] Savoir si un fichier est un exécutable


Sujet :

Free Pascal

  1. #1
    Rédacteur/Modérateur

    [Linux] Savoir si un fichier est un exécutable
    Bonjour !

    Pour savoir si un fichier est un exécutable, sous Linux, y a-t-il mieux que le code suivant ?

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    uses
      SysUtils, Process;
     
    function IsExecutable(const AFileName: string): boolean;
    var
      LCommandOutput: ansistring;
    begin
      if RunCommand('file', [AFileName], LCommandOutput) then
        result := Pos('executable', LCommandOutput) > 0
      else
        result := FALSE;
    end;
     
    begin
      WriteLn(IsExecutable('monfichier'));
    end.

  2. #2
    Expert éminent sénior
    Salut,

    pour moi ça semble bien, puisque ça valide les binaires tout comme les scripts Bash et Python, mais je n'ai pas la prétention de tout savoir.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  3. #3
    Rédacteur/Modérateur

    Citation Envoyé par Jipété Voir le message
    pour moi ça semble bien, puisque ça valide les binaires tout comme les scripts Bash et Python, mais je n'ai pas la prétention de tout savoir.
    Merci Jipété. Oui, ça valide même les exécutables Windows ! Comme ça ne m'arrangeait pas, j'ai modifié ma fonction comme suit :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
        result := (Pos('executable', LCommandOutput) > 0) and (Pos('for MS Windows', LCommandOutput) = 0)


    Le seul inconvénient, c'est que c'est un peu lent, si on doit vérifier un grand nombre de fichiers. Mais enfin ça fonctionne.

  4. #4
    Expert éminent sénior
    Citation Envoyé par Roland Chastain Voir le message
    Oui, ça valide même les exécutables Windows !
    Cela voudrait-il dire que tu balayes plusieurs dossiers dont certains viennent du monde MS et sont accessibles à ton Nux ?
    Donc machine virtuelle MS et dossier partagé ?

    Citation Envoyé par Roland Chastain Voir le message
    Le seul inconvénient, c'est que c'est un peu lent, si on doit vérifier un grand nombre de fichiers.
    Tu m'étonnes que ça prenne du temps,

    Tiens, moi j'écrirais ça comme ça :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      function IsExecutable(const AFileName: string): boolean;
      var
        LCommandOutput: ansistring;
      begin
        LCommandOutput := ''; // happy compilo
        result := FALSE;
        if RunCommand('file', AFileName, LCommandOutput) then // pour quoi faire, tes crochets à AFileName ?
          result := (Pos('executable', LCommandOutput) > 0) and (Pos('for MS Windows', LCommandOutput) = 0)
      end;


    Mais je n'ai pas fait de tests comparatifs sur les temps d'exécution.

    Réflexion de dernière minute : peut-être qu'un filtre sur la présence du bit "executable" des fichiers ferait gagner du temps. C'est à voir…
    Rappel :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    D|-U-|-G-|-W-|
    .|rwx|rwx|rwx|
        ^   ^   ^

    Exemple :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    drwxr-xr-x  9   4096 juin   9  2019 kdenlive --> d indique un dossier, à explorer 
    -rwxr--r--  1   1803 nov.  25  2018 man2text.sh --> à tester
    -rw-r--r--  1 170437 nov.  28  2018 man_rsync.txt --> à NE PAS tester
    -rwxr-xr-x  1     46 nov.  15  2018 memfree.sh --> à tester


    EDIT : pour lister un dossier et n'avoir QUE les droits et le nom des fichiers,
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    stat -c "%A %n" *
    drwxr-xr-x save_files
    lrwxrwxrwx lien
    -rw-r--r-- brasero-session2.log
    -rwxr-xr-x call_fdisk.sh
    -rw-r--r-- dvdstyler.key
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  5. #5
    Rédacteur/Modérateur

    Très intéressant tout ça. Merci Jipété !

    J'ai fait un petit programme qui permet de récupérer le résultat de la commande stat dans une liste de chaînes :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    uses
      Classes, SysUtils, Process;
     
    const
      CBufferSize = 2048;
     
    var
      LProcess: TProcess;
      LStream: TStream;
      LBuffer: array[1..CBufferSize] of byte;
      LBytesRead: longint;
     
    begin
      LProcess := TProcess.Create(nil);
      LProcess.Executable := '/bin/bash';
      LProcess.Parameters.Add('-c');
      LProcess.Parameters.Add('stat -c "%A %n" *');
      LProcess.Options := [poUsePipes];
      LProcess.Execute;
     
      LStream := TMemoryStream.Create;
      repeat
        LBytesRead := LProcess.Output.Read(LBuffer, CBufferSize);
        LStream.Write(LBuffer, LBytesRead)
      until LBytesRead = 0;
      LProcess.Free;
     
      with TStringList.Create do
      begin
        LStream.Position := 0;
        LoadFromStream(LStream);
        WriteLn(Text);
        Free;
      end;
      LStream.Free;
    end.


    Les crochets, c'est à cause de la syntaxe de la fonction RunCommand :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function RunCommand(
      const exename: string;
      const commands: array of string; // <---
      out outputstring: string;
      Options: TProcessOptions = []
    ):Boolean;


    Mais peut-être qu'on peut l'écrire aussi comme tu as fait : je n'ai pas vérifié.

    Oui, j'ai des exécutables Windows dans mes dossiers. Ce que je voudrais faire, c'est trouver tous les exécutables Linux présents dans un dossier et ses sous-dossiers. C'est pour mon jeu d'échecs : je voudrais qu'il soit capable de détecter automatiquement tous les "moteurs" se trouvant dans un certain répertoire.

    Là je pense que j'ai tout ce qu'il faut pour y arriver.

  6. #6
    Expert éminent sénior
    Citation Envoyé par Roland Chastain Voir le message
    Les crochets, c'est à cause de la syntaxe de la fonction RunCommand :
    Mais peut-être qu'on peut l'écrire aussi comme tu as fait : je n'ai pas vérifié.
    Touche à rien : me suis emmêlé les pinceaux dans l'aide entre les deux versions de la fonction,

    Citation Envoyé par Roland Chastain Voir le message
    Là je pense que j'ai tout ce qu'il faut pour y arriver.
    Au boulot !
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  7. #7
    Rédacteur/Modérateur

    Bon, voilà les deux versions du machin. Effectivement, la deuxième version est plus rapide. Merci Jipété !

    Je ne suis pas tout à fait convaincu par mon code, mais ça fonctionne, au moins chez moi.