Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 22/04/2020, à 18:32

Nuliel

[Résolu] extraire des octets d'un tableau de char (C++)

Bonjour,
J'aimerais extraire des données du secteur de boot d'une partition ntfs, mais je n'arrive pas à utiliser la fonction strncpy pour récupérer chaque morceau.
Voici la ligne qui pose problème:

strncpy(boot_sector.oem_id,*(memblock+3),8);

Le 3 correspond à l'offset, et le 8 correspond à la longueur.
memblock est un pointeur sur un tableau de char, oem.id est un tableau de char.

Voici mon code pour l'instant:

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

struct ntfs_boot_sector {

    char oem_id[8];
    char bytes_per_sector[2];
    char sector_per_cluster[1];
    char mft_cluster_number[8];
    char mftmirr_cluster_number[8];
    char bytes_or_Clusters_Per_File_Record_Segment[1];
    char end_of_sector_Marker[2];
} ;

ntfs_boot_sector init_boot_sector(string partition, int offset = 0) {
    struct ntfs_boot_sector boot_sector;
    ifstream file(partition, ios::in|ios::binary);
    if (file.is_open())
    {
        char * memblock;
        memblock = new char [512];
        file.seekg(offset);
        file.read(memblock, 512);
        file.close();
        strncpy(boot_sector.oem_id,*(memblock+3),8);
        cout << boot_sector.oem_id << endl;
        delete[] memblock;
        return boot_sector;
    }
    else cout << "can't open partition or file" << endl;
}

int main() {
    init_boot_sector("bootsector",239616);
    return 0;
}

Est-ce que j'utilise la bonne fonction?
Si vous avez des conseils pour garder un code propre et lisible je veux bien aussi.
Merci d'avance,
Naziel

Dernière modification par Nuliel (Le 22/04/2020, à 21:02)

Hors ligne

#2 Le 22/04/2020, à 19:16

kevlar

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Bonsoir.
Je ne comprends rien au C++, mais cette instruction :

 strncpy(boot_sector.oem_id,*(memblock+3),8);

Est bien supposée copier à partir de l'adresse mémoire pointée par memblock VERS l'adresse mémoire débutant à boot_sector_oem_id ?
Si oui, pourquoi mettre une étoile * devant memblobk et pas & comme en C ?

Par ailleurs, si je comprends à quoi sert l'instruction 'new', memblock a été alloué (créé dynmaiquement) ; donc, je pense que memblock est déjà un pointeur, donc pour strncopy ()  on n'aurait besoin ni de l'étoile (*) ni de l'esperluette (cette dernière & ne serait utile que si le tableau de char était statique).

Je suis peut-être confus, mais je peux résumer çà ainsi : strncpy () travaille sur des adresses mémoire, il suffit d'aller voir son proto sur n'importe quel site sur le C. Et comme ta variable memblock est allouée dynamiquement, l'adresse source est construite quand tu fais ton new(), enfin à mon avis.

Dernière modification par kevlar (Le 22/04/2020, à 19:21)

Hors ligne

#3 Le 22/04/2020, à 19:29

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Merci kevlar.
Effectivement j'avais pas vu qu'il fallait passer des pointeurs, donc on passe à

strncpy(&boot_sector.oem_id,memblock+3,8);

ou en tout cas dans cette idée là (parce qu'il y a encore une erreur:

naziel@naziel-ThinkPad-X220:~/NTFS_Utility$ g++ NTFS_utility.cpp
NTFS_utility.cpp: In function ‘ntfs_boot_sector init_boot_sector(std::__cxx11::string, int)’:
NTFS_utility.cpp:28:9: error: ‘strncpy’ was not declared in this scope
         strncpy(&boot_sector.oem_id,memblock+3,8);
         ^~~~~~~
NTFS_utility.cpp:28:9: note: suggested alternative: ‘wcpncpy’
         strncpy(&boot_sector.oem_id,memblock+3,8);
         ^~~~~~~
         wcpncpy
naziel@naziel-ThinkPad-X220:~/NTFS_Utility$

)

Dernière modification par Nuliel (Le 22/04/2020, à 19:33)

Hors ligne

#4 Le 22/04/2020, à 19:29

kevlar

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je t'ajoute un extrait d'une fonction perso pour te montrer (en C) comment je travaille sur les adresses avec une fonction "cousine" de la tienne :

Variables :

 gchar *tmpStr, buffer[60];/* 12 chars coded in utf8 */

tmpStr est allouée dynamiquement, buffer [] est "statique", fixée à 60 octets (car un caractère utf8 a besoin de 4 octets au maxi, je mets donc un buffer large pour éviter les débordements mémoire 4*12 = 48+marge = 60)

Ensuite, voici comment j'utilise strncpy () en mixant (car c'est nécessaire dans mon cas) ces deux variables :

g_utf8_strncpy (&buffer, tmpStr, 10);

Cet exemple juste pour te montrer comment on fait la copie des octets.
Bon courage, c'est un pb tout simple.

Hors ligne

#5 Le 22/04/2020, à 19:31

kevlar

Re : [Résolu] extraire des octets d'un tableau de char (C++)

encore une fois, je ne connais pas le C++, mais en C, j'ai intérêt à mettre un en-tête sur "string.h" si je veux utiliser strncpy() qui ne fait pas partie des biblios standard.

#include <string.h>

Hors ligne

#6 Le 22/04/2020, à 19:44

kevlar

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Dernière chose : pourquoi ne pas utiliser memcpy() puisque tu travailles sur le système de fichier ? Tu manipules des octets en mémoire, alors ce serait plus naturel, je pense ...  D'autant que tu dois faire une lecture binaire des données stockées par le système de fichiers.

Hors ligne

#7 Le 22/04/2020, à 19:50

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Ok, merci pour l'exemple.
Effectivement il faut inclure cstring ou string.h (c'est ce qu'indique http://www.cplusplus.com/reference/cstr … kw=strncpy ),
avec

strncpy(&boot_sector.oem_id,memblock+3,8);

j'en suis là

NTFS_utility.cpp: In function ‘ntfs_boot_sector init_boot_sector(std::__cxx11::string, int)’:
NTFS_utility.cpp:29:49: error: cannot convert ‘char (*)[8]’ to ‘char*’ for argument ‘1’ to ‘char* strncpy(char*, const char*, size_t)’
         strncpy(&boot_sector.oem_id,memblock+3,8);
                                                 ^

Je comprends pas trop l'erreur, char * correspond juste à un pointeur vers un caractère non?

Edit: effectivement memcpy semble être plus adapté. Je vais essayer d'adapter

Dernière modification par Nuliel (Le 22/04/2020, à 19:53)

Hors ligne

#8 Le 22/04/2020, à 19:56

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Ah, avec

memcpy(&boot_sector.oem_id,memblock+3,8);

ça compile mais j'ai un retour vide, mais normalement je devrais voir NTFS vu que ces 4 caractères là apparaissent dans le champ oem_id.

Hors ligne

#9 Le 22/04/2020, à 21:01

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Ah je suis bête, j'ai fait un dump du secteur de boot, du coup l'offset n'a pas de sens. Mais c'est bizarre qu'il râle pas: je passe un gros offset alors que le fichier fait que 512 octets.
C'est bon, ça fonctionne, je peux du coup récupérer toutes les infos du secteur de boot.

Merci beaucoup!

Hors ligne

#10 Le 23/04/2020, à 07:36

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Salut Naziel,

Pourquoi passer par strncpy? C'est une fonction issue du C, d'où la nécessité d'utiliser string.h. Utilise plutôt la bibliothèque standard, ce que la classe string te met à disposition http://www.cplusplus.com/reference/string/string/. Tu as plusieurs possibilités, en première intention, j'aurais utilisé la méthode substr de la classe string.

De même, j'aurais plutôt fait une classe ntfs_boot_sector dans laquelle soit je stocke le dump du secteur de boot, soit je le lis à chaque fois, avec des assesseurs pour chacun des champs.

Hors ligne

#11 Le 23/04/2020, à 10:00

grigouille

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je te propose une version un peu plus "C++" (sans memcpy)

#include <iostream>
#include <string>
#include <fstream>
#include <cctype>

#define SIZE_TAB(t) sizeof(t)/sizeof(t[0])

struct ntfs_boot_sector {

    char oem_id[8];
    char bytes_per_sector[2];
    char sector_per_cluster[1];
    char mft_cluster_number[8];
    char mftmirr_cluster_number[8];
    char bytes_or_Clusters_Per_File_Record_Segment[1];
    char end_of_sector_Marker[2];
} ;

ntfs_boot_sector init_boot_sector(const std::string& partition, int offset = 0) {
	ntfs_boot_sector boot_sector;
	std::ifstream file(partition, std::ios::binary);
	if (file)
	{
		constexpr int N{512};
		char memblock[N];
		file.seekg(offset);
		file.read(memblock, N);
		file.close();
		const char *p = &memblock[3];
		std::copy(p, p + SIZE_TAB(boot_sector.oem_id), boot_sector.oem_id);
		for(char c : boot_sector.oem_id) {
			std::cout << (isprint(c) ? c : '?');
		}
		std::cout << std::endl;
	}
	else std::cout << "can't open partition or file: " << partition << std::endl;
	return boot_sector;
}

int main() {
    init_boot_sector("bootsector",239616);
    return 0;
}

Dernière modification par grigouille (Le 23/04/2020, à 12:32)


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#12 Le 23/04/2020, à 10:13

Nasman

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Par curiosité, à quoi correspond la valeur de 239616 ?


PC fixe sous Bionic 64 bits et portable avec Focal 64 bits

Hors ligne

#13 Le 23/04/2020, à 10:17

FrancisFDZ

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Bonjour,
Rappel : C++, et depuis C# sont des évolutions de C ; les commandes en C fonctionneront aussi dans ces langages, mais il vaut mieux quand c'est possible utiliser les fonctions propres à ces langages, qui sont plus élaborées.


-- On peut avoir des raisons de se plaindre et n'avoir pas raison de se plaindre --
[Victor Hugo]

Hors ligne

#14 Le 23/04/2020, à 11:05

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

239616 correspond au début de la partition ntfs sur le disque dur (ça commence à partir du secteur 239616), mais comme j'ai fait un dump du premier secteur, cela n'a pas de sens de continuer à utiliser cet offset.

Vu que je récupère le contenu de secteurs d'un disque j'ai pensé à memcpy, et comme j'arrivais pas à l'utiliser j'ai fait des recherches et je suis tombé sur strncpy qui pouvait peut être convenir. Comme ce n'est pas du vrai texte que je récupère mais des fichiers binaires, je pensais que string ne serait pas adapté.

Ok pour le côté plus objet.

Merci grigouille pour le code proposé.
C'est quoi la différence entre

constexpr int N{512};

et

int const N(512);

?

Je ne comprends pas:

#define SIZE_TAB(t) sizeof(t)/sizeof(t[0])

pourquoi diviser par sizeof(t[0])?

Merci à tous pour vos retours.

Hors ligne

#15 Le 23/04/2020, à 11:17

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Naziel a écrit :

Je ne comprends pas:

#define SIZE_TAB(t) sizeof(t)/sizeof(t[0])

pourquoi diviser par sizeof(t[0])?

C'est une macro qui est générique. Elle peut prendre en charge tout type de données, donc t[0] ne vaut pas nécessairement un octet.

En utilisant ce qui est mis à disposition par la bibliothèque standard, ce n'est pas nécessaire. Il y a la méthode size qui donne la taille du string : http://www.cplusplus.com/reference/string/string/size/, l'unité de base de string étant un char.

Hors ligne

#16 Le 23/04/2020, à 11:27

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Ok pour sizeof et size

Dans les données binaires, il est fort probable que je rencontre des caractères qui pourraient être interprétés comme la terminaison de chaîne ou une tabulation ou d'autres trucs du même genre. Cela ne va pas déranger string?

Dernière modification par Nuliel (Le 23/04/2020, à 11:28)

Hors ligne

#17 Le 23/04/2020, à 11:39

Nasman

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je pense que la lecture du contenu devrait s'effectuer octet par octet sans tenir compte de tout ce qui peut être caractère terminal.
C'est en connaissant exactement la structure de la partition ntfs, les octets d'offset xx à yy (en général un multiple de 2) correspondent à tel type d'information. Por ce qui est des chaines, souvent c'est : soit de longueur fixe (padding avec des zéros), soit avec un octet qui indique la longueur de la chaine.


PC fixe sous Bionic 64 bits et portable avec Focal 64 bits

Hors ligne

#18 Le 23/04/2020, à 11:58

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Naziel a écrit :

Dans les données binaires, il est fort probable que je rencontre des caractères qui pourraient être interprétés comme la terminaison de chaîne ou une tabulation ou d'autres trucs du même genre. Cela ne va pas déranger string?

Je ne sais pas répondre à cette question, il faudrait faire l'essai. Si tu as un doute, tu peux utiliser dans ce cas la classe vector typée en char smile

Hors ligne

#19 Le 23/04/2020, à 12:36

grigouille

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Naziel a écrit :

C'est quoi la différence entre

constexpr int N{512};

et

int const N(512);

?

constexpr signifie "être évalué à la compilation". C'est plus dans l'esprit "C++11" d'utiliser constexpr si possible.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#20 Le 23/04/2020, à 12:44

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Alors l'essai suivant:

    string texte = "Hello" + "/n";
        texte = texte + "World";
        cout << texte << endl;

conduit à une erreur

NTFS_utility.cpp:36:32: error: invalid operands of types ‘const char [6]’ and ‘const char [3]’ to binary ‘operator+’
         string texte = "Hello" + "/n";
                        ~~~~~~~~^~~~~~

Conclusion: je vais pas utiliser les string mais des tableaux de char, ce sera mieux

Hors ligne

#21 Le 23/04/2020, à 12:45

grigouille

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Naziel a écrit :

Comme ce n'est pas du vrai texte que je récupère mais des fichiers binaires, je pensais que string ne serait pas adapté.

std::string peut très bien contenir du binaire :

$ cat toto.cpp 
#include <iostream>
#include <string>

int main(int argc, char* argv[]) {
	std::string s;
	s += '\0';
	s += 'a';
	std::cout << s.size() << '\n';
}
$ g++ -o toto toto.cpp
$ ./toto
2
$ 

Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#22 Le 23/04/2020, à 13:43

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Naziel a écrit :
NTFS_utility.cpp:36:32: error: invalid operands of types ‘const char [6]’ and ‘const char [3]’ to binary ‘operator+’
         string texte = "Hello" + "/n";
                        ~~~~~~~~^~~~~~

Tu ne peux pas ajouter 2 constantes. La surcharge de l'opérateur + ne le prend pas en comtpe. (d'autant que cette surcharge n'est pas faite dans la class string http://www.cplusplus.com/reference/stri … operator+/

Voici les combinaisons possibles, fournies par l'opérateur +

string (1)	

string operator+ (const string& lhs, const string& rhs);
string operator+ (string&&      lhs, string&&      rhs);
string operator+ (string&&      lhs, const string& rhs);
string operator+ (const string& lhs, string&&      rhs);

c-string (2)	

string operator+ (const string& lhs, const char*   rhs);
string operator+ (string&&      lhs, const char*   rhs);
string operator+ (const char*   lhs, const string& rhs);
string operator+ (const char*   lhs, string&&      rhs);

character (3)	

string operator+ (const string& lhs, char          rhs);
string operator+ (string&&      lhs, char          rhs);
string operator+ (char          lhs, const string& rhs);
string operator+ (char          lhs, string&&      rhs);

Donc ceci fonctionne :

#include <iostream>
#include <string>

using namespace std;

int main ()
{
		string texte = "\n";
		texte = texte;
		texte = "Hello" + texte + "World";
		cout << texte << endl;
}

Hors ligne

#23 Le 23/04/2020, à 13:48

grigouille

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Naziel a écrit :
NTFS_utility.cpp:36:32: error: invalid operands of types ‘const char [6]’ and ‘const char [3]’ to binary ‘operator+’
         string texte = "Hello" + "/n";
                        ~~~~~~~~^~~~~~

Il faut écrire :

string texte = "Hello"  "/n";

Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#24 Le 23/04/2020, à 13:59

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Ok pour l'opération sur les constantes et pour le type string.

Je crois que c'est mal barré pour faire tout mon programme en C++, il faut que je reprenne un bouquin de C++ là sad

Hors ligne

#25 Le 23/04/2020, à 14:34

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je crois comprendre que "bootsector" est un fichier correspondant au dump du secteur de boot d'une partition ntfs, n'est ce pas?

EDIT : pour moi : http://www.ntfs.com/ntfs-partition-boot-sector.htm

Dernière modification par NicoApi73 (Le 23/04/2020, à 14:41)

Hors ligne