lseek() w bardzo dużym pliku

lseek() w bardzo dużym pliku
KE
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 13 lat
  • Postów:6
0

Dobry wieczór,
jestem tutaj nowy, początkujący :-) i chciałbym się przywitać !

Do rzeczy:
piszę sobie taki prosty program poszukujący sektory na dysku mające sygnaturkę "NTFS " (wiadomo, chodzi o sektory z BB) i mam problem.
Samo przeszukiwanie polega na zmianie wskaźnika pozycji w pliku i poruszanie się po cylindrach.

.....|Sektor 254|Sektor 255|>>>(CYLINDER m-1/255/63)<<<|>>>(CYLINDER m/0/1)<<<|Sektor 0|Sektor 1|.....

(E MATKO, ma być .....|sektor 62|sektor 63| ..... )
(tak to wygląda, a przynajmniej myślę że mój programik odpowiada temu wyżej :-) )

I teraz :
mimo deklaracji zmiennej typu uint64_t zawierającej aktualną pozycje w pliku wartość ta nie przekracza uint32_t !! następuje przepełnienie (chyba) i programik startuje ze zmienna od nowa.
Próbowałem już sztuczek z
#define _FILE_OFFSET_BITS 64 oraz #define _LARGEFILE64_SOURCE
i bawiłem się funkcjami lseek64,open64,fopen64(?),fseeko64(?), a ze zmiennymi off_t i off64_t wyprawiałem cuda na kiju :-) no ale nic nie pomogło.
Sprawdzone na Ubuntu 11.04 32bit i 64bit oraz w kazdej wersji tegoz systemu wartosc zmiennej start_sector w programie gdb zawsze miała 4 bajty, np.

(gdb) print &start_sector
$2 = (uint64_t *) 0x7fffffffe1d8
(gdb) x/4x &start_sector-1
0x7fffffffe1d0: 0x00603130 0x00000000 0xec0ffc00 0x00000000
(gdb)

( 0xec0ffc00 ma być wartością pierwszego przesunięcia pliku pod CHS 2048/255/63 )

Proszę o jakąś radę, albo podpowiedź. NIE LICZĘ NA GOTOWCA :-)

Kopiuj
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE

#include	<stdio.h>
#include	<stdint.h>
#include	<stdlib.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<fcntl.h>
#include	<unistd.h>
#include	<string.h>

// from ntfs-3g - 2011.4.12

// : types.h

typedef uint8_t  u8;			/* Unsigned types of an exact size */
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

typedef int8_t  s8;			/* Signed types of an exact size */
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;

typedef u16 le16;
typedef u32 le32;
typedef u64 le64;

typedef u16 sle16;
typedef u32 sle32;
typedef u64 sle64;

typedef u16 ntfschar;

typedef s64 VCN;
typedef sle64 leVCN;
typedef s64 LCN;
typedef sle64 leLCN;

typedef s64 LSN;
typedef sle64 leLSN;

// END : types.h

// : endians.h

#define __le16_to_cpu(x) (x)
#define __le32_to_cpu(x) (x)
#define __le64_to_cpu(x) (x)

#define __cpu_to_le16(x) (x)
#define __cpu_to_le32(x) (x)
#define __cpu_to_le64(x) (x)

#define __constant_le16_to_cpu(x) (x)
#define __constant_le32_to_cpu(x) (x)
#define __constant_le64_to_cpu(x) (x)

#define __constant_cpu_to_le16(x) (x)
#define __constant_cpu_to_le32(x) (x)
#define __constant_cpu_to_le64(x) (x)

// END : endians.h

// : layout.h

//#define magicNTFS	__constant_cpu_to_le64(0x202020205346544e)	/* "NTFS    " */
unsigned long long int 	magicNTFS = 0x4e54465320202020;
unsigned int 		NTFS_SB_MAGIC = 0x5346544e;			/* 'NTFS' */
unsigned short		SECTOR_MARKER = 0xaa55;

typedef struct {
	u16 bytes_per_sector;		/* Size of a sector in bytes. */
	u8  sectors_per_cluster;	/* Size of a cluster in sectors. */
	u16 reserved_sectors;		/* zero */
	u8  fats;			/* zero */
	u16 root_entries;		/* zero */
	u16 sectors;			/* zero */
	u8  media_type;			/* 0xf8 = hard disk */
	u16 sectors_per_fat;		/* zero */
/*0x0d*/u16 sectors_per_track;		/* Required to boot Windows. */
/*0x0f*/u16 heads;			/* Required to boot Windows. */
/*0x11*/u32 hidden_sectors;		/* Offset to the start of the partition
					   relative to the disk in sectors.
					   Required to boot Windows. */
/*0x15*/u32 large_sectors;		/* zero */
/* sizeof() = 25 (0x19) bytes */
} __attribute__((__packed__)) BIOS_PARAMETER_BLOCK;

typedef struct {
	u8  jump[3];			/* Irrelevant (jump to boot up code).*/
	u64 oem_id;			/* Magic "NTFS    ". */
/*0x0b*/BIOS_PARAMETER_BLOCK bpb;	/* See BIOS_PARAMETER_BLOCK. */
	u8 physical_drive;		/* 0x00 floppy, 0x80 hard disk */
	u8 current_head;		/* zero */
	u8 extended_boot_signature; 	/* 0x80 */
	u8 reserved2;			/* zero */
/*0x28*/s64 number_of_sectors;		/* Number of sectors in volume. Gives
					   maximum volume size of 2^63 sectors.
					   Assuming standard sector size of 512
					   bytes, the maximum byte size is
					   approx. 4.7x10^21 bytes. (-; */
	s64 mft_lcn;			/* Cluster location of mft data. */
	s64 mftmirr_lcn;		/* Cluster location of copy of mft. */
	s8  clusters_per_mft_record;	/* Mft record size in clusters. */
	u8  reserved0[3];		/* zero */
	s8  clusters_per_index_record;	/* Index block size in clusters. */
	u8  reserved1[3];		/* zero */
	u64 volume_serial_number;	/* Irrelevant (serial number). */
	u32 checksum;			/* Boot sector checksum. */
/*0x54*/u8  bootstrap[426];		/* Irrelevant (boot up code). */
	u16 end_of_sector_marker;	/* End of bootsector magic. Always is
					   0xaa55 in little endian. */
/* sizeof() = 512 (0x200) bytes */
} __attribute__((__packed__)) NTFS_BOOT_SECTOR;

// END : layout.h

// END : from ntfs-3g - 2011.4.12

// : DEFINES

int	verbose = 1;

#define DEV		"/dev/"

#define CYLINDERS 	0
#define HEADS		255
#define SECTORS		63
#define SSIZE		512
#define NSEC		4
#define HALF_NSEC	(NSEC/2)

#define CYLINDER_LBA	1 * HEADS * SECTORS
#define CYLINDER_BYTES	CYLINDER_LBA * SSIZE

#define SOF(type,name)	\
	type name;	\
	if(verbose==1)	\
	{		\
	printf("%d: sizeof(", __LINE__);	\
	printf("%s %s", #type, #name);	\
	printf(") == %d\n",sizeof(name));	\
	}

struct harddg {
	unsigned int 	c;
	unsigned char	h;
	unsigned char	s;
} harddg;

void fill_geometry(char *, struct harddg *);

// END : DEFINES

// : FUNCTIONS

void fill_geometry(char *device, struct harddg *g) {
	
	char *LSTR = "/sys/block/";
	char *RSTR = "/size";
	
	//char *devpath = strcat(DEV, device);
	//char *stok = strtok(devpath, "/");
	uint64_t size = 0;
	char *path = (char *)calloc(1,128);
	char *pp = path;
	pp = strcpy(pp, LSTR);
	pp += strlen(pp);
	pp = strcpy(pp, device);
	pp += (strlen(pp));
	pp = strcpy(pp, RSTR);
	
	char *buf = (char *)calloc(1,64);
	
	printf("fill_geometry: path %s\n",path);
	
	if(strstr(path,device)) {
		FILE *p = fopen(path,"rt");
		if(p) {
			fread((char *)buf, 64, 1, p);
			if(buf) {
				size = strtoull(buf,NULL,0); // ???
				uint32_t cylinders = size / HEADS / SECTORS;
				g->c = cylinders;
				g->h = HEADS;
				g->s = SECTORS;
				fclose(p);
				//return size;
			} else {
				printf("fill_geometry: %s not readed\n",path);
				fclose(p);
				//return 0;
			}
		} else {
			printf("fill_geometry: %s not opened\n",path);
			//return 0;
		}
	} else {
		printf("fill_geometry: string %s error\n",device);
		//return 0;
	}
	
}
// END : FUNCTIONS
int main(int argc, char *argt[]) {
	if(argc<2) {
		printf("%s: use eg. %s sda\n",argt[0],argt[0]);
		return 1;
	}

	char *progname 	= argt[0];
	char *device 	= argt[1];

	char *devpath = (char *)calloc(1,10);
	devpath = strcpy(devpath, DEV);
	devpath = strcat(devpath, device);
	
	if(argc==2 && device && (strlen(device)==3 || strlen(device)==4)) {
		struct harddg *hdg = (struct harddg *)calloc(1,sizeof(struct harddg));
			
		fill_geometry(device, hdg);
		//if(!size) {
		//	printf("%s: fill_geometry error\n", progname);
		//	return 1;
		//}
		
		int devicef = open64(devpath, O_LARGEFILE | O_RDONLY, "rb");
		//FILE *devicef = fopen(devpath, "rb");
		if(!devicef) {
			printf("%s: device %s not opened\n", progname, device);
			return 1;
		}
		
		//fseek(devicef,0L,SEEK_SET);
		
		unsigned int start_cylinder = 2048;
		unsigned int end_cylinder = hdg->c;
		
		SOF(uint64_t,start_sector);//= (start_cylinder * HEADS * SECTORS * SSIZE) - (SSIZE * HALF_NSEC);
		
		//fseek(devicef, start_sector, SEEK_SET);
		int nsec = 0;
		
		for( ; start_cylinder<end_cylinder+1; start_cylinder++) {
			start_sector = (start_cylinder * HEADS * SECTORS * SSIZE) - (SSIZE * HALF_NSEC);
			if(lseek64(devicef, start_sector, SEEK_SET)<0) {
				printf("%s: Error seek not set\n", progname);
				//fclose(devicef);
				close(devicef);				
				return 1;
			}
			char *buffer = (char *)calloc(SSIZE*NSEC,1);
			//size_t readed = fread(buffer, 1, SSIZE*NSEC, devicef);
			size_t readed = read(devicef, buffer, 1 * SSIZE*NSEC);
			if(!(start_cylinder%1024))
				printf("%s:\tCYLINDER: %d\n",progname,start_cylinder);
			if(!(start_sector%(1*1024*1024)))
				printf("%s:\t\tOFFSET: %lu\n",progname,start_sector);
			for(nsec = 0; nsec < NSEC; nsec++) {
				NTFS_BOOT_SECTOR *ntfs_bs = (NTFS_BOOT_SECTOR *)&buffer[nsec*SSIZE];
				if(ntfs_bs->oem_id==magicNTFS) 
				{
					printf("%s: MAGICNTFS found on \
					%u/%d cylinder\n", progname, start_cylinder, nsec);
				}
			}
			free(buffer);
			//start_sector = (start_cylinder * HEADS * SECTORS * SSIZE) - (SSIZE * HALF_NSEC);
			//fseek(devicef, start_sector, SEEK_SET);
		}
		
		close(devicef);
	} else {
		printf("%s: bad arguments\n", progname);
	}
}
 
edytowany 1x, ostatnio: kedziorno
KE
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 13 lat
  • Postów:6
0

Nikt nie pomoże ?

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:dzień
0

za duży kawałek kodu, mało czytelny post (jakieś cyferki - literki, jeśli już to powinny być w znacznikach < code >), wielu to odstrasza na sam widok i nie czytają dalej.

MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:4 minuty
0

dodaj do tego, że okrasiłeś temat dość wąską specjalistyczną wiedzą na temat NTFS (na dodatek mam wrażenie, że pomieszałeś różne poziomy abstrakcji: "przeszukiwanie polega na zmianie wskaźnika pozycji w pliku i poruszanie się po cylindrach"), a temat nie wzbudzi zainteresowania.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
KE
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 13 lat
  • Postów:6
0

Aha.
W takim razie sorki.
Azarien: myślałem że jest ok, już poprawiam.
MarekR22: napisałem na początku że jestem początkujący :-) Sam cytat nie jest stwierdzeniem/powtórzeniem jakiejś definicji lecz moimi słowami :-)
W każdym razie nie chodzi o specjalistyczną wiedzę NTFS, bo sam takowej nie posiadam. Znam tylko podstawowe struktury danych i podstawy łączenia LCNów dla atrybu, indeksu, informacji o pliku... Moje pytanie dotyczyło prostej rzeczy, mianowicie czemu mimo użycia 64bitowych wartości w dodatku w 64bit. systemie, programik nalicza mi zmienną dla unsigned int jak w 32bit. architekturze i jaki powinien byc prawidłowy typ zmiennej. Zniknęły mi tablice partycji na 320gb dysku (czysty 1 sektor) no a nie pamiętam jak mw. były rozmieszczone. W dodatku powiem że program TestDisk również nie wskazał prawidłowych wartości.

KE
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 13 lat
  • Postów:6
0

...
piszę sobie taki prosty program poszukujący sektory na dysku mające sygnaturkę "NTFS " (wiadomo, chodzi o sektory z BB) i mam problem.

Poszukiwanie tychże sektorów to nic innego jak prosta zmiana pozycji w pliku funkcją seek wyliczoną wg. LBA512=cylinder255*63 bajtów.
Aby się zabezpieczyć przed 'ślepym szczałem' programik czyta sektor na początku danego cylindra dysku (cylinder/0/1) start_sector, 2 sektory przed start_sector oraz jeden za start_sector. W sumie 4 sektory (czyli 2048bajtów) i jeżeli znajdzie w którymś z 4 sektorów sygnaturkę, wyświetla odpowiedni monit.

Wizualnie (tu: model logiczny) wygląda to tak:
.....|Cm-1/H255/S62|Cm-1/H255/S63|>>>(koniec cylindra m-1/255/63, na dysku ten obszar między |>>> a <<< ** NIE ISTNIEJE !)<<<|>>>(początek cylindra m/0/1, na dysku ten obszar między >>> a <<<| ** NIE ISTNIEJE !)<<<|Cm/H0/S1|Cm/H0/S2|.....

Znak : | - oznacza 512bajtów, C to cylinder, H to głowice, S to sektory
Komentarze między >>> a <<< to po prostu komentarze i nie mają wpływu na nic prócz uświadomienia :-)

a prościej

|C1/H0/S1|C1/H0/S2|...//**|C1/H255/S62|C1/H255/S63|C2/H0/S1|C2/H0/S2|**//...|Cx/H255/S63|
Między | i | są 512b bloki a podkreślony podciąg to bloki czytane dla 2 cylindra.

I teraz :
mimo deklaracji zmiennej typu **uint64_t start_sector ** zawierającej aktualną pozycje w pliku wartość ta nie przekracza uint32_t (czyli mimo zastosowania 64bit architektury, naliczanie zmiennej zatrzymuje sie na wartości 4 miliardy coś tam i leci od początku) !!
Próbowałem już sztuczek z

Kopiuj
 #define _FILE_OFFSET_BITS 64 
#define _LARGEFILE64_SOURCE

(man lseek64(3))

i bawiłem się funkcjami lseek64,open64,fopen64(?),fseeko64(?), a ze zmiennymi off_t i off64_t wyprawiałem cuda na kiju :-) no ale nic nie pomogło.
Sprawdzone na Ubuntu 11.04 32bit i 64bit oraz w kazdej wersji tegoz systemu wartosc zmiennej **start_sector ** w programie gdb zawsze miała 4 bajty (a nie 8 bajtów tak jak mówi dokumentacja i intuicja).

Poniżej kod z programu gdb poleceniem
gdb -ggdb -o program program.c

Kopiuj
(gdb) print &start_sector
$2 = (uint64_t *) 0x7fffffffe1d8
(gdb) x/4x &start_sector-1
0x7fffffffe1d0:        0x00603130        0x00000000        0xec0ffc00        0x00000000
(gdb)

(pierwsze to adres zmiennej start_sector w pamięci ($2) a 2 polecenie to adres zmiennej $2 - 1 (czyli xBAJTÓW-8BAJTÓW :-) ) wypisana w formie 32bitowych wartości 4 razy)

(Przepraszam za takie szczegółowe rozpisanie. Nie wiem jak do tego podejść, bo dla mnie takie rzeczy są oczywiste :-) )
Proszę o jakąś radę, albo podpowiedź. NIE LICZĘ NA GOTOWCA :-)

edytowany 5x, ostatnio: kedziorno
KE
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 13 lat
  • Postów:6
0

Witam !

Programik ruszył, zmienna jest juz OK.
Pozdrawiam.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)