#1 Le 22/04/2020, à 17: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, à 20:02)
Hors ligne
#2 Le 22/04/2020, à 18: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, à 18:21)
Hors ligne
#3 Le 22/04/2020, à 18: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, à 18:33)
Hors ligne
#4 Le 22/04/2020, à 18: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, à 18: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, à 18: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, à 18: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, à 18:53)
Hors ligne
#8 Le 22/04/2020, à 18: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, à 20: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, à 06: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, à 09: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, à 11:32)
Debian (xfce) 12
HP LaserJet M1132 MFP
Hors ligne
#12 Le 23/04/2020, à 09: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, à 09: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, à 10: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, à 10:17
- NicoApi73
Re : [Résolu] extraire des octets d'un tableau de char (C++)
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, à 10: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, à 10:28)
Hors ligne
#17 Le 23/04/2020, à 10: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, à 10:58
- NicoApi73
Re : [Résolu] extraire des octets d'un tableau de char (C++)
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
Hors ligne
#19 Le 23/04/2020, à 11:36
- grigouille
Re : [Résolu] extraire des octets d'un tableau de char (C++)
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, à 11: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, à 11:45
- grigouille
Re : [Résolu] extraire des octets d'un tableau de char (C++)
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, à 12:43
- NicoApi73
Re : [Résolu] extraire des octets d'un tableau de char (C++)
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, à 12:48
- grigouille
Re : [Résolu] extraire des octets d'un tableau de char (C++)
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, à 12: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à
Hors ligne
#25 Le 23/04/2020, à 13: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, à 13:41)
Hors ligne