Revisione 2006.12.01. Originale aggiornato: http://www.insulae.net/doc/disk.cloning.it.php
2006.06.10 - 2006.08.13 - 2006.12.01
Occorrente
Deframmentazione
Esame del disco di origine
Azzeramento dello spazio libero sul disco di origine
Creazione dell'immagine
Azzeramento del disco di destinazione
Copia dell'immagine sul disco di destinazione
Ridimensionamento della partizione
Tabella riassuntiva
Questo documento descrive un modo per creare un'immagine del disco fisso con un sistema operativo installato, usando i comandi dd e parted di Linux, e ripristinarla su un disco di dimensioni uguali, maggiori o minori di quello di partenza.
Nel caso illustrato il disco contiene un'installazione di Windows 98 SE in una sola partizione, ma il metodo descritto permette di clonare anche dischi divisi in più partizioni, ridimensionando l'ultima per adattarla al disco di destinazione.
Viene copiata nell'immagine la porzione iniziale del disco di origine contenente i dati, compreso l'MBR, in modo da ottenere una copia avviabile.
Il disco fisso con il sistema da clonare. Prima di installare Windows ho azzerato il disco di origine, per cancellare dati spuri che l'azzeramento post installazione non sempre elimina, vi ho creato con SystemRescueCD una partizione FAT32 LBA (*) che ho formattato dal CD di Windows 98 nel corso della procedura di installazione.
(*) Perché l'immagine di un disco di sistema sia avviabile su un disco di geometria diversa, occorre che la partizione d'avvio di entrambi i dispositivi sia LBA. In questo modo, durante l'installazione del sistema operativo, la posizione d'inizio del kernel viene scritta nel settore di avvio della partizione in coordinate LBA (Linear Block Address), indipendenti dalla geometria del disco, e durante l'avvio il boot loader trova il kernel alla posizione specificata anche su un disco di geometria diversa.
La versione di fdisk del CD di Windows 98 crea una partizione di tipo b FAT32 e non c FAT32 (LBA), per cui, non rilevando una partizione LBA, il programma di installazione di Windows scrive la posizione del kernel in coordinate CHS (cylinder, head, sector). Se il punto a cui inizia il kernel è specificato indicando cilindro, testina e settore, invece dell'indirizzo lineare del blocco di byte, su un disco di geometria diversa gli stessi valori (c, h, s) indicheranno un blocco di dati differente e il boot loader non troverà il kernel, arrestandosi con il messaggio "Disco non di avvio. Sostituire il disco e premere un tasto.
". Perciò ho creato la partizione LBA con fdisk di Linux. Ringrazio alex.tg per queste informazioni.
Un disco di destinazione, preferibilmente pure esso azzerato.
Un terzo disco ausiliario su cui creare l'immagine del disco origine, da cui ripristinarla sul disco di destinazione.
Per semplificare diciamo disco, ma quanto scritto dovrebbe funzionare per ogni dispositivo a blocchi avviabile che supporti LBA.
Un sistema Linux da cui eseguire le operazioni, ad esempio il CD-ROM live di SystemRescueCD.
A voler essere pignoli, occorrerebbe avviare SystemRescueCD in modo che si carichi ed esegua interamente in RAM, per evitare lo swap sul disco di cui creare l'immagine. La relativa opzione passata al kernel avvia però il sistema con la tastiera inglese, senza chiedere la lingua della tastiera come fa l'avvio normale. In attesa di una conoscenza più completa dei parametri da passare, lo eseguo com'è anche se usa il disco come spazio di swap.
La distribuzione Linux usata dovrebbe comprendere GNU parted, un potente programma della FSF per manipolare le partizioni.
Nel seguito si usa anche il comando defrag di Windows per compattare i dati sul disco da clonare, benché non sia strettamente necessario dato che parted può svolgere lo stesso compito.
Nota. nel seguito uso il termine dispositivo come equivalente di disco (ad esempio, hda è un dispositivo) mentre programmi come fdisk usano device come sinonimo di partizione. In attesa di chiarimenti, non impuntiamoci sui cavilli.
Il comando dd usato per creare l'immagine esegue una copia fisica, blocco per blocco, del disco di origine. Non è necessario copiare l'intero dispositivo: basta la parte iniziale occupata dai dati, che comprende l'MBR e il settore d'avvio della partizione.
La deframmentazione concentra lo spazio occupato dai dati all'inizio del disco, eliminando gli spazi vuoti. In questo modo, i byte allocati dai file presenti sul disco corrispondono grosso modo al numero di byte da copiare nell'immagine.
Cancello dal disco di origine tutto il superfluo – programmi non usati, cache del browser, contenuto di cartelle temporanee, voci superflue nel registro di sistema. Nel mio caso questa ripulitura non è stata necessaria perché il sistema era appena installato.
Collego il disco di origine come secondario master di un sistema Windows, da cui lo deframmento con il programma defrag. In alternativa, posso eseguire la deframmentazione dal disco di origine stesso. Chissà che succede se manca la corrente.
In Risorse del computer, clic destro sull'icona del disco (D:) e nella finestra Proprietà - (D:) dalla scheda Strumenti premo il pulsante Esegui Defrag. Visualizzando i dettagli si può vedere il processo che ridispone i cluster occupati all'inizio dell'unità.
Pare inoltre che lo stesso parted possa essere usato per deframmentare. Attendo di saperne di più e provare.
Esaminando il disco cerchiamo di capire quanto spazio sia occupato dalle strutture relative all'organizzazione del disco e dai file, che la deframmentazione ha concentrato nella parte iniziale della partizione, per sapere quanti byte copiare nell'immagine.
Al termine della deframmentazione, segno lo spazio allocato da tutti i file:
Proprietà - (D:) dà
totale: 4.309.794.816 byte 4,01 GB occupato: 337.588.224 byte 331 MB disponibile: 3.972.206.592 3,68 GB
mentre dalla cartella D:\, selezionando tutto e scegliendo Proprietà dal menu contestuale,
2.776 file, 151 cartelle dimensione: 331.974.912 byte 325 MB utilizzati: 336.912.384
piacevolmente diverso dal risultato precedente.
Il numero di byte utilizzati (allocati) da tutti i file è minore dello spazio occupato perché questo comprende il contenuto del settore d'avvio della partizione, della tabella di allocazione dei file e di altre eventuali strutture del file system.
Collego il disco come primario master hda, e come secondario master hdc il disco destinato a riceverne l'immagine.
Avvio da SystemRescueCD, ed esamino la geometria del disco e le dimensioni in byte, per confrontarli con i dati forniti da Windows:
/ % fdisk /dev/hda (m) (p)
Disk /dev/hda: 4325 MB, 4325529600 bytes 255 heads, 63 sectors/track, 525 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System ------------------------------------------------------------ /dev/hda1 * 1 525 4217031 c W95 FAT32 (LBA)
/ % cfdisk /dev/hda
Disk Drive: /dev/hda Size: 4325529600 bytes, 4325 MB Heads: 255 Sectors per track: 63 Cylinders: 525 Name Flags Part Type FS Type [Label] Size (MB) --------------------------------------------------------------------- hda1 Boot Primary W95 FAT32 (LBA) 4318.28
/ % sfdisk -l /dev/hda
Disk /dev/hda: 525 cylinders, 255 heads, 63 sectors/track Units: cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0 Device Boot Start End #cyls #blocks Id System ---------------------------------------------------------------------------- /dev/hda1 * 0+ 524 525- 4217031 c W95 FAT32 (LBA) /dev/hda2 0 - 0 0 0 Empty /dev/hda3 0 - 0 0 0 Empty /dev/hda4 0 - 0 0 0 Empty
N.B. attenzione all'opzione -l: senza di essa sfdisk /dev/hda entra in modalità interattiva e attende comandi per modificare la tabella delle partizioni, senza fornire un menu come fdisk. Un errore e il disco è partito! Sono uscito premendo CTRL+X.
Conviene esaminare anche con parted quanto spazio è occupato sulla partizione da clonare.
/ % parted /dev/hda
(parted) print
Disk geometry for /dev/ide/host0/bus0/target0/lun0/disc: 0.000-4125.146 megabytes Disk label type: msdos Minor Start End Type Filesystem Flags 1 0.031 4118.225 primary fat32 boot, lba
(parted) print 1
Minor: 1 Flags: boot, lba File System: fat32 Size: 4118.194Mb (99%) Minimum size: 330.681Mb (8%) Maximum size: 4125.146Mb (100%)
(parted) quit
Cercando di individuare un senso nei valori numerici restituiti, confrontiamo i valori dati in byte dai ?fdisk con quelli di parted in megabyte, arrotondati alla terza cifra decimale,
4325529600 dato da fdisk pare un qualche massimo spazio disponibile sul disco.
Infatti, convertendo in megabyte e arrotondando,
4325529600 / (1024 × 1024) = 4125,146484375 ≈ 4125,146
corrisponde al valore dichiarato da parted come massima dimensione possibile per la partizione.
4318239744 = 4217031 blocchi di 1024 byte, dati da ?fdisk, corrisponde alle dimensioni della partizione secondo parted:
4318239744 / (1024 × 1024) = 4118,1943359375 ≈ 4118,194
parted individua l'inizio della partizione dopo 32256 = 63 × 512 byte, corrispondenti ai 63 settori della prima traccia: infatti
32256 / (1024 × 1024) = 0,03076171875 ≈ 0,031
Quindi, la partizione inizia sul primo cilindro, ma dopo la prima traccia: questo mi ricorda che mi sembra di aver letto da qualche parte che inizio e fine di una partizione debbano coincidere con i confini di una traccia, ma non so se sia un vincolo obbligatorio o dipendente dal programma usato per creare la partizione (*). Poiché il primo settore (512 byte) è riservato ad MBR e tabella delle partizioni, l'intera prima traccia viene lasciata vuota e la partizione inizia con la seconda.
(*) Notare che parted non sembra ragionare in termini di unità CHS, che non sono neppure menzionate nel suo output – forse però si permette di ignorarle perché la partizione è LBA. Potrebbe essere che i confini di questa particolare partizione coincidano con quelli di tracce perché essa è stata creata con fdisk.
Il numero di byte corrispondente a 525 cilindri, dove fdisk individua la fine della partizione,
4318272000 = 525 cylinders × 8225280 bytes per cylinder
4318272000 / (1024 × 1024) = 4118,22509765625 ≈ 4118,225
si accorda col valore dichiarato da parted.
Le dimensioni della partizione, date come fine meno inizio, risultano 4318272000 − 32256 = 4318239744, come appena visto.
Di questi, 4309794816 byte sono dichiarati disponibili da Windows. Parte della partizione è infatti dedicata al settore d'avvio della stessa, alla tabella di allocazione dei file (FAT, File Allocation Table) e ad eventuali altre strutture del file system FAT32. La differenza tra le dimensioni della partizione e lo spazio disponibile,
4318239744 − 4309794816 = 8444928 = 16494 × 512 = 8247 × 1024, non mi suggerisce nulla.
La dimensione massima per la partizione, 4325529600 byte, più la prima traccia, 32256 byte, dovrebbero dare lo spazio totale:
4325529600 + 32256 = 4325561856 byte, 4325561856 / (1024 × 1024) = 4125,17724609375 ≈ 4125,177 megabyte.
Vediamo che la partizione creata da fdisk non occupa tutto il disco, ma lascia dello spazio libero. Queste dimensioni per la partizione sono state determinate accettando il valore di default calcolato da fdisk come massimo possibile, che corrisponde al maggior numero intero di cilindri ricavabili dal disco, meno la prima traccia.
La differenza tra la massima dimensione possibile per la partizione e l'attuale,
4325529600 − 4318272000 = 7257600 < 8225280 byte, non basta infatti a fare un cilindro.
Pare che parted possa permettere di creare o ridimensionare la partizione fino all'intero spazio disponibile, senza essere vincolato dai confini delle tracce o cilindri.
Ci interessa conoscere quanto spazio su disco sia occupato dal contenuto della prima traccia più la partizione per copiare, dopo aver deframmentato i dati in settori contigui nella parte iniziale del dispositivo, solo la porzione di disco occupata per ottenere un file immagine dalle minori dimensioni possibili.
Copiando il dispositivo blocco per blocco, dal primo settore in avanti, occorre sapere quanti byte corrispondano ai settori occupati per troncare la copia dopo l'ultimo byte occupato, nella parte libera del disco. I 336912384 byte dichiarati allocati da Windows non sono significativi perché si riferiscono al solo spazio occupato dai file, senza contare le strutture del file system.
Molto più interessante è la minima dimensione possibile per la partizione, dichiarata da parted,
330,681 MB = 330,681 × 1024 × 1024 = 346744160,256 ≈ 346744160 bytes
che dovrebbe contare tutti i byte allocati dai file e dalle strutture del file system nella partizione. Sommata ai 32256 byte della prima traccia, occupata dall'MBR e dalla tabella delle partizioni, dà 346776416 byte, una stima ragionevole dello spazio occupato sul disco.
Ovviamente la quantità di spazio occupato dipende da cosa è installato. Il valore di 330,681 MB corrisponde a un'installazione personalizzata del solo sistema operativo Windows 98 SE, senza applicazioni e driver aggiuntivi, effettuata in precedenza.
Prudenzialmente, copieremo nell'immagine un numero di byte ampiamente maggiore del valore calcolato. Il restante spazio vuoto verrà riempito di zeri o quasi al passo seguente, per essere compresso più efficacemente.
Quindi, copieremo nell'immagine 700.000 blocchi di 512 byte, per un totale di 358.400.000 byte.
Devo provare se riducendo con parted la partizione al minimo la copia di hda con dd si arresti da sola alla fine della partizione, non trovandone altre, invece di proseguire fino alla fine dello spazio fisicamente esistente sul disco. In altre parole, è una domanda su come sia fatto il file speciale /dev/hda, dove finisca e quali ne siano le dimensioni.
In tale caso converrebbe ridurre la partizione al minimo, o poco più, anche perché mi sembra d'aver letto – forse sul manuale di parted – che deframmentare non sarebbe necessario in quanto parted, mentre ridimensiona una partizione, provvede anche a copiare i dati in essa presenti in forma contigua. In tal caso parted, prima di creare l'immagine, fungerebbe da utilità di deframmentazione / sostituirebbe / renderebbe superflua la deframmentazione sotto Windows.
Dopo l'ultimo byte occupato, un certo numero di byte inutilizzati verrà copiato nel file immagine. Conviene fare in modo che sul disco di origine lo spazio libero dai file sia il più possibile occupato da byte tutti uguali, ad esempio il carattere NUL corrispondente all'esadecimale 0x00, così che l'immagine del disco, compressa, occupi poco spazio.
Esistono programmi per Windows, ad esempio il noto Eraser, che tra le proprie funzionalità comprendono lo riempimento dello spazio libero con una stringa scelta dall'utente. Un modo alla buona per farlo da Linux è usare il comando dd per creare uno o più file formati da zeri fino a riempire l'intero spazio disponibile, e poi cancellarli lasciando sul posto i byte azzerati.
Montata la partizione come /mnt/hda1,
/ % mkdir /mnt/hda1 / % mount -t vfat /dev/hda1 /mnt/hda1
ne riempio di zeri lo spazio libero:
/ % dd if=/dev/zero of=/mnt/hda1/filler
Si tratta di creare un file filler contenente zeri (0x00) e accrescerlo fino a riempimento dell'unità. Poiché i byte occupati sono stati compattati all'inizio della partizione fino a un certo punto, lasciando byte in prevalenza liberi di lì in avanti fino alla fine, questo file occupa quasi consecutivamente tutti i byte disponibili dal primo blocco libero fino al termine della partizione. Finito di creare il file, i blocchi precedentemente liberi conterranno in prevalenza zeri binari – non completamente perché, presumo, certi byte erano già occupati da dati relativi a strutture del file system.
La creazione del file prosegue fino al messaggio
zsh: file size limit exceeded
che avverte di aver raggiunto il limite per le dimensioni di un file.
Il numero di byte del file filler creato è infatti 2147483647 = 2 × 10243 − 1, meno dello spazio disponibile.
Perché questo limite di 2 GB − 1 alla dimensione di un file? All'inizio ho pensato al limite di 2 GB delle vecchie versioni di dd, di cui parla tomsrtbt, ma la versione di SystemRescueCD dovrebbe essere abbastanza recente e, comunque, il file si tronca a 2 GB − 1 anche usando cat per crearlo. Quindi ho pensato a una limitazione intrinseca del file system, ma FAT32 permette file di dimensioni fino a 4 GB. Da quanto ho letto, pare essere un limite di Linux, sulla cui natura attendo di sapere di più.
Creo allora un secondo file di riempimento filler2, con lo stesso comando di cui sopra o con
/ % cat /dev/zero > /mnt/hda1/filler2
fino al messaggio
cat: write error: No space left on device
che avverte finalmente dell'avvenuto riempimento del disco. Le dimensioni di filler2 sono di 1824722944 byte, che sommati ai 2147483647 di filler danno un totale di 3972206591, un byte in meno dei 3972206592 dichiarati liberi da Windows.
Per unità di grandi dimensioni, si continua a creare file di zeri fino a riempire l'intero spazio a disposizione.
Controllo che i file di riempimento siano effettivamente fatti di soli zeri:
/ % mc (F3) / % hexdump -C /mnt/hda1/filler | less
mostrano difficoltà, perché il file da visualizzare è troppo grosso per stare in memoria e, essendo il disco completamente pieno, non vi è spazio disponibile per lo swap.
Cancello infine i file di riempimento,
/ % cd /mnt/hda1 /mnt/hda1 % rm filler (y) /mnt/hda1 % rm filler2 (y)
sicché a questo punto la partizione hda1 dovrebbe contenere i file di Windows e spazio vuoto in prevalenza occupato da zeri.
Un esame con
/ % hexdump -C /dev/hda1 | less
e, partendo quasi dall'inizio del presunto spazio libero,
/ % hexdump -C -s 300000000 /dev/hda1
mostra che lo spazio non occupato non ha tutti zeri, ma è fatto di sezioni di zeri inframmezzate da sezioni contenenti configurazioni simili. Ad esempio dalla locazione esadecimale 0x00410880 = 4262016 alla 0x00410c80 = 4263040 esclusa ci sono i seguenti dati,
00410880 21 00 00 00 22 00 00 00 23 00 00 00 24 00 00 00 |!..."...#...$...|
00410890 25 00 00 00 26 00 00 00 27 00 00 00 28 00 00 00 |%...&...'...(...|
004108a0 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 |)...*...+...,...|
004108b0 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 |-......./...0...|
004108c0 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 |1...2...3...4...|
004108d0 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 |5...6...7...8...|
004108e0 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 |9...:...;...<...|
004108f0 3d 00 00 00 3e 00 00 00 3f 00 00 00 ff ff ff 0f |=...>...?.......|
00410900 41 00 00 00 42 00 00 00 43 00 00 00 44 00 00 00 |A...B...C...D...|
00410910 45 00 00 00 46 00 00 00 47 00 00 00 48 00 00 00 |E...F...G...H...|
00410920 49 00 00 00 4a 00 00 00 4b 00 00 00 4c 00 00 00 |I...J...K...L...|
00410930 4d 00 00 00 4e 00 00 00 4f 00 00 00 50 00 00 00 |M...N...O...P...|
00410940 51 00 00 00 52 00 00 00 53 00 00 00 54 00 00 00 |Q...R...S...T...|
00410950 55 00 00 00 56 00 00 00 57 00 00 00 58 00 00 00 |U...V...W...X...|
00410960 59 00 00 00 5a 00 00 00 5b 00 00 00 5c 00 00 00 |Y...Z...[...\...|
00410970 5d 00 00 00 5e 00 00 00 5f 00 00 00 60 00 00 00 |]...^..._...`...|
00410980 61 00 00 00 62 00 00 00 63 00 00 00 64 00 00 00 |a...b...c...d...|
00410990 65 00 00 00 66 00 00 00 67 00 00 00 68 00 00 00 |e...f...g...h...|
004109a0 69 00 00 00 6a 00 00 00 6b 00 00 00 6c 00 00 00 |i...j...k...l...|
004109b0 6d 00 00 00 6e 00 00 00 6f 00 00 00 70 00 00 00 |m...n...o...p...|
004109c0 71 00 00 00 72 00 00 00 73 00 00 00 74 00 00 00 |q...r...s...t...|
004109d0 75 00 00 00 76 00 00 00 77 00 00 00 78 00 00 00 |u...v...w...x...|
004109e0 79 00 00 00 7a 00 00 00 7b 00 00 00 7c 00 00 00 |y...z...{...|...|
004109f0 7d 00 00 00 7e 00 00 00 7f 00 00 00 80 00 00 00 |}...~...........|
00410a00 81 00 00 00 82 00 00 00 83 00 00 00 84 00 00 00 |................|
00410a10 85 00 00 00 86 00 00 00 87 00 00 00 88 00 00 00 |................|
00410a20 89 00 00 00 8a 00 00 00 8b 00 00 00 8c 00 00 00 |................|
00410a30 8d 00 00 00 8e 00 00 00 8f 00 00 00 90 00 00 00 |................|
00410a40 91 00 00 00 92 00 00 00 93 00 00 00 94 00 00 00 |................|
00410a50 95 00 00 00 96 00 00 00 97 00 00 00 98 00 00 00 |................|
00410a60 99 00 00 00 9a 00 00 00 9b 00 00 00 9c 00 00 00 |................|
00410a70 9d 00 00 00 9e 00 00 00 9f 00 00 00 a0 00 00 00 |................|
00410a80 a1 00 00 00 a2 00 00 00 a3 00 00 00 a4 00 00 00 |................|
00410a90 a5 00 00 00 a6 00 00 00 a7 00 00 00 a8 00 00 00 |................|
00410aa0 a9 00 00 00 aa 00 00 00 ab 00 00 00 ac 00 00 00 |................|
00410ab0 ad 00 00 00 ae 00 00 00 af 00 00 00 b0 00 00 00 |................|
00410ac0 b1 00 00 00 b2 00 00 00 b3 00 00 00 b4 00 00 00 |................|
00410ad0 b5 00 00 00 b6 00 00 00 b7 00 00 00 b8 00 00 00 |................|
00410ae0 b9 00 00 00 ba 00 00 00 bb 00 00 00 bc 00 00 00 |................|
00410af0 bd 00 00 00 be 00 00 00 bf 00 00 00 c0 00 00 00 |................|
00410b00 c1 00 00 00 c2 00 00 00 c3 00 00 00 c4 00 00 00 |................|
00410b10 c5 00 00 00 c6 00 00 00 c7 00 00 00 c8 00 00 00 |................|
00410b20 c9 00 00 00 ca 00 00 00 cb 00 00 00 cc 00 00 00 |................|
00410b30 cd 00 00 00 ce 00 00 00 cf 00 00 00 d0 00 00 00 |................|
00410b40 d1 00 00 00 d2 00 00 00 d3 00 00 00 d4 00 00 00 |................|
00410b50 d5 00 00 00 d6 00 00 00 d7 00 00 00 d8 00 00 00 |................|
00410b60 d9 00 00 00 da 00 00 00 db 00 00 00 dc 00 00 00 |................|
00410b70 dd 00 00 00 de 00 00 00 df 00 00 00 e0 00 00 00 |................|
00410b80 e1 00 00 00 e2 00 00 00 e3 00 00 00 e4 00 00 00 |................|
00410b90 e5 00 00 00 e6 00 00 00 e7 00 00 00 e8 00 00 00 |................|
00410ba0 e9 00 00 00 ea 00 00 00 eb 00 00 00 ec 00 00 00 |................|
00410bb0 ed 00 00 00 ee 00 00 00 ef 00 00 00 f0 00 00 00 |................|
00410bc0 f1 00 00 00 f2 00 00 00 f3 00 00 00 f4 00 00 00 |................|
00410bd0 f5 00 00 00 f6 00 00 00 f7 00 00 00 f8 00 00 00 |................|
00410be0 f9 00 00 00 fa 00 00 00 fb 00 00 00 fc 00 00 00 |................|
00410bf0 fd 00 00 00 fe 00 00 00 ff 00 00 00 00 01 00 00 |................|
00410c00 01 01 00 00 02 01 00 00 03 01 00 00 04 01 00 00 |................|
00410c10 05 01 00 00 06 01 00 00 07 01 00 00 08 01 00 00 |................|
00410c20 09 01 00 00 0a 01 00 00 0b 01 00 00 0c 01 00 00 |................|
00410c30 0d 01 00 00 0e 01 00 00 0f 01 00 00 10 01 00 00 |................|
00410c40 11 01 00 00 12 01 00 00 13 01 00 00 14 01 00 00 |................|
00410c50 15 01 00 00 16 01 00 00 17 01 00 00 18 01 00 00 |................|
00410c60 19 01 00 00 1a 01 00 00 1b 01 00 00 1c 01 00 00 |................|
00410c70 1d 01 00 00 1e 01 00 00 1f 01 00 00 20 01 00 00 |............ ...|
e a 0x00410c80 ricominciano dati simili, ma non uguali. Fra le due locazioni ci sono 4263040 − 4262016 = 1024 byte: quindi, questo tipo di struttura si ripete ogni 1024 byte. Poiché hda è stato azzerato prima di iniziare, suppongo che tale struttura sia stata generata dalla formattazione – perché sopravvive all'azzeramento dello spazio libero tramite file di riempimento.
Creo un'immagine del disco così preparato sul disco secondario master hdc:
/ % mkdir /mnt/hdc1 / % mount -t vfat /dev/hdc1 /mnt/hdc1 / % dd if=/dev/hda of=/mnt/hdc1/hda.img bs=512 count=700000
La copia inizia silenziosa, ed è abbastanza veloce. Il numero di blocchi da copiare è stato stabilito in modo da eccedere lo spazio occupato. Il file hda.img ottenuto ha 358.400.000 byte, come specificato.
Troncare la copia del disco origine al numero di blocchi strettamente necessari genera un file delle minime dimensioni possibili.
L'immagine ottenuta, una volta verificatane l'integrità, cioè che la copia non abbia troncato il file in un punto in cui ci sono ancora dati, può essere ripristinata su qualsiasi disco che abbia dimensioni maggiori dell'immagine, anche minori di quelle del disco di partenza. Esempio: il disco origine ha 4 GB, l'immagine è di 350 MB: posso copiare l'immagine su qualsiasi disco di dimensioni superiori a 350 MB, quindi anche più piccolo del disco di partenza. Il solo requisito è che il disco d'origine e quello di destinazione siano abilitati all'indirizzamento LBA dei blocchi – qualsiasi disco fabbricato dopo il (1996?) dovrebbe esserlo – e la partizione in cui è stato installato il sistema sia di tipo LBA.
Un rudimentale controllo dell'integrità dell'immagine copiata consiste nel verificare che al fondo il file contenga zeri, o la struttura di byte rilevata nello spazio libero in /dev/hda, e che i dati significativi terminino prima della fine.
Esaminato con mc, il file hda.img mostra una lunga serie di zeri (*) al fondo, fino alla riga 0x155cbff0 la cui ultima posizione è 0x155cbfff = 358399999. Poiché il conto comincia da zero, ci sono in effetti 700.000 blocchi.
Risalendo all'indietro, trovo zeri fino a 0x151cf645, a partire dal quale, all'indietro, si trova una pagina HTML che pare contenere un messaggio di sistema. 0x151cf645 = 354219589, l'ultima locazione occupata, contiene il carattere > del contrassegno di chiusura </HTML>. Prima della pagina, l'immagine contiene zeri fino a quella che sembra la fine dei dati.
Prima e dopo tale pagina, dunque, zeri.
Alla posizione corrispondente alla dimensione dei file dichiarata da Windows, 331974912 = 0x13C98900, intorno e indietro, zeri. Alla posizione corrispondente ai byte allocati dichiarati da Windows, 336912384 = 0x1414E000 e intorno, zeri; lo stesso intorno alla posizione corrispondente allo spazio occupato dichiarato da Windows, 337588224 = 0x141F3000.
Ho incontrato questa pagina creando immagini di diverse dimensioni, per cui sembrerebbe intenzionalmente scritta da Windows, non un residuo dei dati presenti in precedenza sul disco origine. Ma perché si trova oltre i limiti dello spazio dichiarato come allocato, come pure oltre la minima dimensione che parted può assegnare alla partizione? Cos'è? A cosa serve? Tagliarla fuori dall'immagine quali conseguenze produrrebbe?
Eccedere nel numero di blocchi da copiare, count=700000, è stato quindi saggio.
(*) Notare che il visualizzatore esadecimale di mc mostra nello spazio libero dell'immagine tutti zeri, mentre hexdump visualizza la configurazione di byte vista in /dev/hda. Quindi, mc considera come zeri 0x00 dei caratteri che per hexdump non lo sono?
Maldido! Passando dalla visualizzazione hex-ASCII alla ASCII mc torna all'inizio del file, vanificando un quarto d'ora di dito premuto su PG Giù.
A parte il mistero della pagina situata oltre la fine dei dati, l'immagine si presenta integra.
Il file ottenuto hda.img contiene l'immagine del disco hda con la partizione hda1. Non si può ovviamente montare, perché si tratta di un dispositivo, non una partizione, ma è istruttivo esaminarlo con fdisk e compagni per un confronto con /dev/hda:
/mnt/hdc1 % fdisk hda.img
dà
You must set cylinders. You can do this from the extra functions menu. Command (m for help): p Disk hda.img: 0 MB, 0 bytes 255 heads, 63 sectors/track, 0 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System -------------------------------------------------------------- hda.img1 * 1 525 4217031 c W95 FAT32 (LBA) Command (m for help): q
mentre
/mnt/hdc1 % cfdisk hda.img
risponde
FATAL ERROR: Cannot get disk size Press any key to exit cfdisk
e infine
/mnt/hdc1 % sfdisk -l hda.img
elenca dettagliatamente
Disk hda.img: cannot get size Disk hda.img: cannot get geometry Disk hda.img: 0 cylinders, 0 heads, 0 sectors/track Warning: The partition table looks like it was made for C/H/S=*/255/63 (instead of 0/0/0). For this listing I'll assume that geometry. Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0 Device Boot Start End #cyls #blocks Id System ------------------------------------------------------------------------------- hda.img1 * 0+ 524 525- 4217031 c W95 FAT32 (LBA) hda.img2 0 - 0 0 0 Empty hda.img3 0 - 0 0 0 Empty hda.img4 0 - 0 0 0 Empty
Il comando
/mnt/hdc1 % gzip -9 hda.img
sostituisce un file compresso hda.img.gz all'originale hda.img, che viene distrutto. Invece,
/mnt/hdc1 % gzip -c9 hda.img > hda.img.gz
con l'opzione
-c = "write output to standard output, keep original file unchanged" (**)
lascia hda.img intatto e dirige l'output di gzip nel file compresso hda.img.gz.
(**) Senza l'opzione -c,
/mnt/hdc1 % gzip -9 hda.img > hda.out.gz
gzip sostituirebbe il file originale hda.img con quello compresso hda.img.gz, e non invia dati allo standard output, creando perciò un file hda.out.gz vuoto. Ho specificato un nome diverso per non creare conflitti tra i due file creati simultaneamente da gzip.
Decomprimendo hda.img.gz, ottenuto indifferentemente in uno dei due modi,
/mnt/hdc1 % gzip -d hda.img.gz
(gzip con l'opzione -d equivale a gunzip) si riottiene il file originale hda.img, che sostituisce il file compresso.
Con le istruzioni sopra illustrate ho dapprima creato l'immagine hda.img del file speciale /dev/hda corrispondente al dispositivo collegato come master sul primo canale IDE, quindi ho compresso l'immagine ottenuta in un file hda.img.gz, dopo aver controllato che fosse intera.
Saltando la verifica dell'integrità, si può creare direttamente l'immagine compressa in un solo passo, combinando dd e gzip:
/ % dd if=/dev/hda bs=512 count=700000 | gzip -9 > /mnt/hdc1/hda.img.gz
In questa concatenazione, dd copia 700000 blocchi del file /dev/hda allo standard output; gzip senza specificare un nome di file come argomento legge dallo standard input e scrive sullo standard output, rediretto nel file /mnt/hdc1/hda.img.gz. Il pipe collega lo standard output di dd allo standard input di gzip.
Nota. L'opzione -c di gzip non si specifica perché essa dice di scrivere sullo standard output, e conservare il file, quando viene specificato un file. Senza un nome di file per argomento, gzip legge e scrive già da sé dagli input e output standard.
L'immagine creata e compressa simultaneamente, concatenando i comandi dd e gzip, ha un numero di byte leggermente minore di quella creata con dd e poi compressa con gzip (nel caso illustrato, 198551473 contro 198551482). Entrambe possono essere decompresse con gzip e copiate con dd, oppure concatenando i due comandi come descritto di seguito.
Per indicare che è stato ottenuto copiando e comprimendo simultaneamente, posso chiamare all'immagine hda.imgz invece di hda.img.gz. In questo caso gzip -d hda.imgz non riconosce l'estensione .imgz e per decomprimere il file occorre rinominarlo; combinando però dd e gzip come di seguito, l'immagine compressa viene ripristinata indipendentemente dal nome.
Prima di copiarvi l'immagine, meglio azzerare il disco di destinazione per cancellare eventuali dati lasciati dal precedente proprietario. Non è necessario sia partizionato e formattato, perché trasferirvi l'immagine ricrea la struttura del disco originale. Lo collego come hda (primario master) e avvio SystemRescueCD, da cui lo riempio di zeri
/ % dd if=/dev/zero of=/dev/hda
fino ad esaurimento dello spazio.
/ % mkdir /mnt/hdc1 / % mount -t vfat /dev/hdc1 /mnt/hdc1 / % cd /mnt/hdc1
A questo punto l'immagine compressa hda.img.gz si trova in /mnt/hdc1 per essere ripristinata sul disco di destinazione, collegato come hda e azzerato.
Si può decomprimere l'immagine compressa come hda.img, e quindi copiarlo sul disco di destinazione,
/mnt/hdc1 % gzip -d hda.img.gz /mnt/hdc1 % dd if=hda.img of=/dev/hda
oppure decomprimere e copiare in una sola operazione:
/mnt/hdc1 % gzip -cd hda.img.gz | dd of=/dev/hda
700000+0 records in 700000+0 records out
gzip -d decomprime il file specificato e, per via dell'opzione -c, scrive senza cancellarlo sullo standard output redirezionato allo standard input di dd. Poiché il file da decomprimere viene esplicitamente specificato, la combinazione di comandi funziona qualunque sia il nome dell'immagine compressa, anche hda.imgz.
Esaminando hda con fdisk,
/ % fdisk /dev/hda (avviso sul numero di cilindri superiore a 1024) Command (m for help): p Disk /dev/hda: 8455 MB, 8455200768 bytes 255 heads, 63 sectors/track, 1027 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System ------------------------------------------------------------------ /dev/hda1 * 1 525 4217031 c W95 FAT32 (LBA)
riconosce una partizione hda1, grande quanto quella d'origine, su un disco più grande.
Montando la partizione hda1 per guardarne il contenuto,
/ % mkdir /mnt/hda1 / % mount -t vfat /dev/hda1 /mnt/hda1 / % ls -al /mnt/hda1
/mnt/hda1 contiene i file di Windows come sul disco d'origine.
Il dispositivo di destinazione contiene una partizione e spazio non partizionato, nel quale è possibile creare altre partizioni. Il disco si è avviato e ho provato, per esperimento, a creare con fdisk una seconda partizione.
Creando per esperimento una seconda partizione,
/ % fdisk /dev/hda
Command (m for help): n
p primary partition (1-4)
Partition number (1-4): 2
First cylinder (526-1027, default 526): [invio]
Last cylinder or ... (526-1027, default 1027): [invio]
Command (m for help): p
Disk /dev/hda: 8455 MB, 8455200768 bytes
255 heads, 63 sectors/track, 1027 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
------------------------------------------------------------
/dev/hda1 * 1 525 4217031 b W95 FAT32
/dev/hda2 526 1027 4032315 83 Linux
fdisk di SystemRescueCD crea automaticamente una partizione Linux.
Cancellata la seconda partizione, operando con parted ridimensiono la partizione hda1:
/ % parted /dev/hda
(parted) print
Disk geometry for /dev/ide/host0/bus0/target0/lun0/disc: 0.000-8063.507 megabytes
Disk label type: msdos
Minor Start End Type Filesystem Flags
1 0.031 4118.225 primary fat32 boot, lba
Si osservi che la partizione hda1 ripristinata dall'immagine occupa, secondo parted che legge la tabella delle partizioni, i 4 GB del disco di origine, non i byte corrispondenti ai 700000 blocchi copiati nell'immagine.
Chiedendo informazioni dettagliate sulla partizione,
(parted) print 1
parted fornisce la dimensione della partizione, la minima dimensione che essa può assumere in base ai file che contiene, e la massima dimensione assegnabile, dipendente dallo spazio sul disco:
Minor: 1 Flags: boot, lba File System: fat32 Size: 4118.194Mb (51%) Minimum size: 330.681Mb (4%) Maximum size: 8063.508Mb (100%)
Ridimensiono la partizione hda1 specificando come nuova dimensione il valore indicato da parted come massima dimensione possibile – a esser pignoli occorre sommare tale dimensione 8063,508 ai 0,0308 megabyte del punto di inizio,
(parted) resize
Partition number? 1
Start? [0.0308]? [Invio]
End? [4118.2246]? 8063.508
moving data... 100% (time left 00:00) p1
riesamino la partizione ed esco da parted:
(parted) print
Disk geometry for /dev/ide/host0/bus0/target0/lun0/disc: 0.000-8063.507 megabytes
Disk label type: msdos
Minor Start End Type Filesystem Flags
1 0.031 8056.032 primary fat32 boot, lba
(parted) print 1
Minor: 1
Flags: boot, lba
File System: fat32
Size: 8056.002Mb (99%)
Minimum size: 338.367Mb (4%)
Maximum size: 8063.508Mb (100%)
(parted) quit
La dimensione assegnata alla partizione non coincide esattamente con lo spazio disponibile sul disco, che avevo indicato di assegnare, perché i limiti delle partizioni devono coincidere con quelli delle tracce (cilindri?).
Da provare. Magari, nel dire a parted i megabyte a cui far finire la partizione, avessi sommato alla dimensione 8063,508 gli 0,0308 megabyte a cui inizia, avrei potuto raggiungere la fine del disco.
Nota. Provare a usare parted sul file hda.img dell'immagine risulta in un messaggio d'errore. Riprovare, perché avevo letto che si può: forse ho usato parted sull'immagine compressa invece che sull'immagine.
Esaminando nuovamente hda con fdisk,
/ % fdisk /dev/hda (avviso sul numero di cilindri superiore a 1024) Command (m for help): p Disk /dev/hda: 8455 MB, 8455200768 bytes 255 heads, 63 sectors/track, 1027 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System ------------------------------------------------------------ /dev/hda1 * 1 1027 8249346 c W95 FAT32 (LBA)
la partizione hda1 si estende ora sull'intero disco.
Mi pare di aver letto che parted permette di spostare la fine di una partizione senza danneggiare i dati, ma non l'inizio. Quindi, se nel frattempo parted non è cambiato, il metodo descritto serve a copiare tra dischi di dimensioni differenti immagini che constino di una o più partizioni, purché si ridimensioni sul disco di destinazione soltanto l'ultima di esse.
Riavviando il computer dal disco di destinazione, sia prima che dopo il ridimensionamento della partizione, Windows si avvia e funziona come di consueto.
Per esperimento, ho inserito il disco appena preparato su un altro computer. All'avvio Windows 98 ha reinstallato controller e periferiche di sistema, e pure il video dato che ha trovato il driver specifico nella cartella c:\win98 (col che si è riavviato a più colori mentre prima, essendo installato il driver VGA generico, era a 16 colori). Rimesso sul computer per il quale l'ho preparato, si è avviato come prima senza obiezioni.
Immagino dunque che avviando un disco di sistema su diversi computer, installando e configurando tutto ciò che chiede, si crei un sistema predisposto per avviarsi su diverse macchine con configurazioni diverse, che all'avvio rileva da sé la configurazione e vi si adatta. Un disco preparato in questo modo potrebbe essere utile in ambito aziendale, per continuare a lavorare su un'altra macchina se quella su cui lo si usa si guasta. Chissà se questa possibilità esiste anche con le versioni successive di Windows.
Azzerare il disco origine, crearvi una partizione LBA, installare il sistema, deframmentare con defrag o parted.
Azzerare lo spazio libero sul disco origine
/ % mkdir /mnt/hda1 / % mount -t vfat /dev/hda1 /mnt/hda1 / % dd if=/dev/zero of=/mnt/hda1/filler
riempiendolo con file formati di zeri.
Copiare N blocchi del disco origine in un file compresso posto in un disco ausiliario:
/ % mkdir /mnt/hdc1 / % mount -t vfat /dev/hdc1 /mnt/hdc1 / % dd if=/dev/hda bs=512 count=N | gzip -9 > /mnt/hdc1/hda.img.gz
Per un disco con una sola partizione, si assume N superiore alla dimensione minima della partizione calcolata da parted, più la dimensione della prima traccia.
Collegare il disco di destinazione al posto del disco origine, azzerarlo
/ % dd if=/dev/zero of=/dev/hda
e trasferirvi l'immagine situata sul disco ausiliario:
/ % mkdir /mnt/hdc1 / % mount -t vfat /dev/hdc1 /mnt/hdc1 / % gzip -cd /mnt/hdc1/hda.img.gz | dd of=/dev/hda
Infine, ridimensionare la partizione ripristinata sul disco di destinazione:
/ % parted /dev/hda
(parted) print elenca le partizioni presenti e i corrispondenti identificativi,
(parted) print 1 comunica dettagli sulla partizione specificata, fra cui la massima dimensione assegnabile,
(parted) resize chiede quali inizio e fine assegnare alla partizione su cui operare:
Partition number? 1
Start? [0.0308]? [Invio]
End? [4118.2246]? 8063.508
(parted) quit esce.
Questo documento ti è stato utile? Aiutami a migliorarlo inviando suggerimenti, correzioni, risposte.
Autore: Gatto Selvaggio. L'autore si riserva ogni diritto applicabile. L'uso da parte di terzi è soggetto a una licenza Creative Commons. Per usi non contemplati da tale licenza, compreso l'uso commerciale, o in caso di dubbi, si prega di attenersi al precetto "chiedete e vi sarà detto".
6287 visite dal 5 gennaio 2011