[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: pytanie o zrobienie ghosta z NT-kiem



On Tue, May 25, 2004 at 04:49:32PM +0200, Piotr Pruszczak wrote:
> Mam bardzo nietypowe pytanie :
> 
> czy Knoppixem zrobię dokładny obraz dysku z NT 4.0 ??
> jutro jestem daleko - wawa, no i niestety nie dysponuję GHOST'em
> a muszę zrobić dokładny obraz dysku

Niedawno probowalem zrobic cos takiego (chodzilo o to, zeby przy pomocy
linuksa zrobic to, co potrafi ghost), tyle ze partycja byla Windows 98.
Problem polega na tym, ze ghost nie czyta dysku tak jak "dd" (bajt po
bajcie), ale bardziej jak dump (wykorzystujac informacje na temat
struktury systemu plikow omija podczas czytania puste miejsca). Efekt:
czytanie i pisanie przy pomocy dd zajmuje duzo wiecej czasu niz ghostowi.

O ile w moim przypadku czytanie partycji (czyli tworzenie obrazu) moglo
sobie trwac ile chcialo, to przywracanie obrazu na dysk musialo sie z
pewnych wzgledow miescic ponizej 10 minut. O ile ghost radzil sobie z
tym w okolicach 5 minut, to zwykle "dd" musialo na to poswiecic prawie
pol godziny. Jest to oczywiscie zrozumiale, bo ghost nie zapisywal na
dysk bezuzytecznych sektorow, a "dd" pisalo dokladnie wszystko.

Wymyslilem wiec takie cos:

1) zapelniamy zerami partycje pod windows (dd if=/dev/zero of=/dev/partycja)
2) formatujemy ja
3) instalujemy na tym windows i potrzebne oprogramowanie
4) zczytujemy obraz przy pomocy dd if=/dev/partycja | gzip -c > obraz.bin.gz
5) zapisujemy obraz spowrotem na partycje przy pomocy gzip -dc obraz.bin.gz | programik /dev/partycja

"programik" to mial byc maly programik otwierajacy urzadzenie
/dev/parycja i kopiujacy na niego dane z stdin na podobnej zasadzie jak
dd, ale z jednym wyjatkiem: jesli kopiowany sektor zawieralby tylko
zera, to zamiast write() wykonywane byloby wywolanie lseek(). Dzieki
temu bylyby zapisywane tylko uzyteczne sektory. Dodatkowe odraczanie
lseek() tak dlugo jak to mozliwe pozwoliloby zmniejszyc ilosc syscalli.

W razie koniecznosci zmodyfikowania obrazu wykonywane bylyby kroki: 5 a
nastepnie 4. Dzieki temu zapelnianie pustych miejsc smieciami w trakcie
normalnej ekslploatacji systemu nie mialoby znaczenia.

Liczylem na spory zysk na wydajnosci w kroku "5" (bo tylko na nim mi
zalezalo) dzieki znacznemu zmniejszeniu ilosci danych kopiowanych na
dysk (zera przesylane bylyby tylko przez potok miedzy gzipem a
programikiem, co powinno byc stosunkowo szybkie).

W efekcie napisalem programik "holewrite" (zalacznik), ale jest z nim
jeden problem: nie obsluguje duzych partycji (powyzej 2 GB z hakiem).
Probowalem kompilowac go z roznymi dziwnymi flagami preprocesora
majacymi wlaczyc 64-bitowe sycalle, ale jakos nic to nie dawalo, a ja
nie mialem czasu zaglebic sie w temat. Jesli komus uda sie zmusic go do
poprawnego dzialania na duzych partycjach, to bardzo prosze o
instrukcje/latke.

pozdrawiam,

Marcin
-- 
Marcin Owsiany <porridge@debian.org>             http://marcin.owsiany.pl/
GnuPG: 1024D/60F41216  FE67 DA2D 0ACA FC5E 3F75  D6F6 3A0D 8AA0 60F4 1216
#define _GNU_SOURCE 1
#define _LARGEFILE_SOURCE 1

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

#define BLKSIZE 512

int main(int argc, char **argv)
{
	char *name;
	int fd;
	ssize_t n, i;
	off_t skip = (off_t) 0;
	char buf[BLKSIZE];

	if (argc != 2) {
		fprintf(stderr, "Usage: holewrite <device>\n");
		exit(1);
	} else
		name = argv[1];

	if ((fd = open(name, O_RDWR, 0600)) < 0) {
		perror("open()");
		exit(1);
	}

	while ((n = read(0, buf, BLKSIZE)) >= (ssize_t) 0) {
		if (n == (ssize_t) 0) /* EOF */
			exit(0);

		/*
		 * check if we read anything different than zeros
		 */
		for (i = (ssize_t) 0; buf[i] == 0 && i < n; i++) ;
		if (i == n) { /* nope, only zeros */
			/*
			 * just remember to skip the block before next read
			 */
			skip += (off_t) n;
		} else {
			/*
			 * There was something non-zero, so:
			 *  - first skip what we needed to skip, and forget that value
			 *  - then write the block
			 */
			if (skip != (off_t) 0) {
				if (lseek(fd, skip, SEEK_CUR) == (off_t)-1) {
					perror("lseek()");
					exit(1);
				}
				skip = (off_t) 0;
			}
			if (write(fd, buf, (size_t) n) != n) {
				perror("write()");
				exit(1);
			}
		}
			
	}
	perror("read()");
	exit(1);
}


Reply to: