7695d53235ee3913cdfd9d6de225897f0d95103b
[people/sha0/winvblock.git] / src / util / mount.c
1 /**
2  * Copyright 2006-2008, V.
3  * Portions copyright (C) 2009, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
4  * For WinAoE contact information, see http://winaoe.org/
5  *
6  * This file is part of WinVBlock, derived from WinAoE.
7  *
8  * WinVBlock is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * WinVBlock is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /**
23  * @file
24  *
25  * Mount command
26  *
27  */
28
29 #include <windows.h>
30 #include <winioctl.h>
31 #include <stdio.h>
32
33 #include "winvblock.h"
34 #include "portable.h"
35 #include "mount.h"
36 #include "aoe.h"
37
38 typedef enum
39 { CommandScan, CommandShow, CommandMount, CommandUmount, CommandAttach,
40   CommandDetach
41 } COMMAND;
42
43 static void
44 Help (
45   void
46  )
47 {
48   printf ( "winvblk <scan|show|mount|umount|attach|detach>\n\n" );
49   printf ( "  scan\n        Shows the reachable AoE targets.\n\n" );
50   printf ( "  show\n        Shows the mounted AoE targets.\n\n" );
51   printf ( "  mount <client mac address> <major> <minor>\n"
52            "        Mounts an AoE target.\n\n" );
53   printf ( "  umount <disk number>\n        Unmounts an AoE disk.\n\n" );
54   printf ( "  attach <filepath> <disk type> <cyls> <heads> <sectors>\n"
55            "        Attaches <filepath> disk image file.\n"
56            "        <disk type> is 'f' for floppy, 'c' for CD/DVD, "
57            "'h' for HDD\n\n" );
58   printf ( "  detach <disk number>\n"
59            "        Detaches file-backed disk.\n\n" );
60 }
61
62 int
63 main (
64   int argc,
65   char **argv,
66   char **envp
67  )
68 {
69   COMMAND Command;
70   HANDLE DeviceHandle;
71   winvblock__uint8 InBuffer[sizeof ( mount__filedisk ) + 1024];
72   winvblock__uint8 String[256];
73   aoe__mount_targets_ptr Targets;
74   aoe__mount_disks_ptr Disks;
75   winvblock__uint8 Mac[6];
76   DWORD BytesReturned;
77   winvblock__uint32 Major,
78    Minor,
79    Disk;
80   winvblock__uint32 i;
81
82   if ( argc < 2 )
83     {
84       Help (  );
85       goto end;
86     }
87
88   if ( strcmp ( argv[1], "scan" ) == 0 )
89     {
90       Command = CommandScan;
91     }
92   else if ( strcmp ( argv[1], "show" ) == 0 )
93     {
94       Command = CommandShow;
95     }
96   else if ( strcmp ( argv[1], "mount" ) == 0 )
97     {
98       Command = CommandMount;
99     }
100   else if ( strcmp ( argv[1], "umount" ) == 0 )
101     {
102       Command = CommandUmount;
103     }
104   else if ( strcmp ( argv[1], "attach" ) == 0 )
105     {
106       Command = CommandAttach;
107     }
108   else if ( strcmp ( argv[1], "detach" ) == 0 )
109     {
110       Command = CommandDetach;
111     }
112   else
113     {
114       Help (  );
115       printf ( "Press enter to exit\n" );
116       getchar (  );
117       goto end;
118     }
119
120   DeviceHandle =
121     CreateFile ( "\\\\.\\" winvblock__literal, GENERIC_READ | GENERIC_WRITE,
122                  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,
123                  NULL );
124   if ( DeviceHandle == INVALID_HANDLE_VALUE )
125     {
126       printf ( "CreateFile (%d)\n", ( int )GetLastError (  ) );
127       goto end;
128     }
129
130   switch ( Command )
131     {
132       case CommandScan:
133         if ( ( Targets =
134                ( aoe__mount_targets_ptr )
135                malloc ( sizeof ( aoe__mount_targets ) +
136                         ( 32 * sizeof ( aoe__mount_target ) ) ) ) == NULL )
137           {
138             printf ( "Out of memory\n" );
139             break;
140           }
141         if ( !DeviceIoControl
142              ( DeviceHandle, IOCTL_AOE_SCAN, NULL, 0, Targets,
143                ( sizeof ( aoe__mount_targets ) +
144                  ( 32 * sizeof ( aoe__mount_target ) ) ), &BytesReturned,
145                ( LPOVERLAPPED ) NULL ) )
146           {
147             printf ( "DeviceIoControl (%d)\n", ( int )GetLastError (  ) );
148             free ( Targets );
149             break;
150           }
151         if ( Targets->Count == 0 )
152           {
153             printf ( "No AoE targets found.\n" );
154           }
155         else
156           {
157             printf
158               ( "Client NIC          Target      Server MAC         Size\n" );
159             for ( i = 0; i < Targets->Count && i < 10; i++ )
160               {
161                 sprintf ( String, "e%lu.%lu      ", Targets->Target[i].Major,
162                           Targets->Target[i].Minor );
163                 String[10] = 0;
164                 printf
165                   ( " %02x:%02x:%02x:%02x:%02x:%02x  %s  %02x:%02x:%02x:%02x:%02x:%02x  %I64uM\n",
166                     Targets->Target[i].ClientMac[0],
167                     Targets->Target[i].ClientMac[1],
168                     Targets->Target[i].ClientMac[2],
169                     Targets->Target[i].ClientMac[3],
170                     Targets->Target[i].ClientMac[4],
171                     Targets->Target[i].ClientMac[5], String,
172                     Targets->Target[i].ServerMac[0],
173                     Targets->Target[i].ServerMac[1],
174                     Targets->Target[i].ServerMac[2],
175                     Targets->Target[i].ServerMac[3],
176                     Targets->Target[i].ServerMac[4],
177                     Targets->Target[i].ServerMac[5],
178                     ( Targets->Target[i].LBASize / 2048 ) );
179               }
180           }
181         free ( Targets );
182         printf ( "Press enter to exit\n" );
183         getchar (  );
184         break;
185       case CommandShow:
186         if ( ( Disks =
187                ( aoe__mount_disks_ptr ) malloc ( sizeof ( aoe__mount_disks ) +
188                                                  ( 32 *
189                                                    sizeof
190                                                    ( aoe__mount_disk ) ) ) ) ==
191              NULL )
192           {
193             printf ( "Out of memory\n" );
194             break;
195           }
196         if ( !DeviceIoControl
197              ( DeviceHandle, IOCTL_AOE_SHOW, NULL, 0, Disks,
198                ( sizeof ( aoe__mount_disks ) +
199                  ( 32 * sizeof ( aoe__mount_disk ) ) ), &BytesReturned,
200                ( LPOVERLAPPED ) NULL ) )
201           {
202             printf ( "DeviceIoControl (%d)\n", ( int )GetLastError (  ) );
203             free ( Disks );
204             break;
205           }
206         if ( Disks->Count == 0 )
207           {
208             printf ( "No AoE disks mounted.\n" );
209           }
210         else
211           {
212             printf
213               ( "Disk  Client NIC         Server MAC         Target      Size\n" );
214             for ( i = 0; i < Disks->Count && i < 10; i++ )
215               {
216                 sprintf ( String, "e%lu.%lu      ", Disks->Disk[i].Major,
217                           Disks->Disk[i].Minor );
218                 String[10] = 0;
219                 printf
220                   ( " %-4lu %02x:%02x:%02x:%02x:%02x:%02x  %02x:%02x:%02x:%02x:%02x:%02x  %s  %I64uM\n",
221                     Disks->Disk[i].Disk, Disks->Disk[i].ClientMac[0],
222                     Disks->Disk[i].ClientMac[1], Disks->Disk[i].ClientMac[2],
223                     Disks->Disk[i].ClientMac[3], Disks->Disk[i].ClientMac[4],
224                     Disks->Disk[i].ClientMac[5], Disks->Disk[i].ServerMac[0],
225                     Disks->Disk[i].ServerMac[1], Disks->Disk[i].ServerMac[2],
226                     Disks->Disk[i].ServerMac[3], Disks->Disk[i].ServerMac[4],
227                     Disks->Disk[i].ServerMac[5], String,
228                     ( Disks->Disk[i].LBASize / 2048 ) );
229               }
230           }
231         free ( Disks );
232         printf ( "Press enter to exit\n" );
233         getchar (  );
234         break;
235       case CommandMount:
236         sscanf ( argv[2], "%02x:%02x:%02x:%02x:%02x:%02x", ( int * )&Mac[0],
237                  ( int * )&Mac[1], ( int * )&Mac[2], ( int * )&Mac[3],
238                  ( int * )&Mac[4], ( int * )&Mac[5] );
239         sscanf ( argv[3], "%d", ( int * )&Major );
240         sscanf ( argv[4], "%d", ( int * )&Minor );
241         printf ( "mounting e%d.%d from %02x:%02x:%02x:%02x:%02x:%02x\n",
242                  ( int )Major, ( int )Minor, Mac[0], Mac[1], Mac[2], Mac[3],
243                  Mac[4], Mac[5] );
244         memcpy ( &InBuffer[0], Mac, 6 );
245         *( winvblock__uint16_ptr ) ( &InBuffer[6] ) =
246           ( winvblock__uint16 ) Major;
247         *( winvblock__uint8_ptr ) ( &InBuffer[8] ) =
248           ( winvblock__uint8 ) Minor;
249         if ( !DeviceIoControl
250              ( DeviceHandle, IOCTL_AOE_MOUNT, InBuffer, sizeof ( InBuffer ),
251                NULL, 0, &BytesReturned, ( LPOVERLAPPED ) NULL ) )
252           {
253             printf ( "DeviceIoControl (%d)\n", ( int )GetLastError (  ) );
254           }
255         break;
256       case CommandUmount:
257         sscanf ( argv[2], "%d", ( int * )&Disk );
258         printf ( "unmounting disk %d\n", ( int )Disk );
259         memcpy ( &InBuffer, &Disk, 4 );
260         if ( !DeviceIoControl
261              ( DeviceHandle, IOCTL_AOE_UMOUNT, InBuffer, sizeof ( InBuffer ),
262                NULL, 0, &BytesReturned, ( LPOVERLAPPED ) NULL ) )
263           {
264             printf ( "DeviceIoControl (%d)\n", ( int )GetLastError (  ) );
265           }
266         break;
267       case CommandAttach:
268         {
269           mount__filedisk filedisk;
270           char obj_path_prefix[] = "\\??\\";
271
272           if ( argc < 6 )
273             {
274               printf ( "Too few parameters.\n" );
275               Help (  );
276               CloseHandle ( DeviceHandle );
277               return 1;
278             }
279           filedisk.type = *argv[3];
280           sscanf ( argv[4], "%d", ( int * )&filedisk.cylinders );
281           sscanf ( argv[5], "%d", ( int * )&filedisk.heads );
282           sscanf ( argv[6], "%d", ( int * )&filedisk.sectors );
283           memcpy ( &InBuffer, &filedisk, sizeof ( mount__filedisk ) );
284           memcpy ( &InBuffer[sizeof ( mount__filedisk )], obj_path_prefix,
285                    sizeof ( obj_path_prefix ) );
286           memcpy ( &InBuffer
287                    [sizeof ( mount__filedisk ) + sizeof ( obj_path_prefix ) -
288                     1], argv[2], strlen ( argv[2] ) + 1 );
289           if ( !DeviceIoControl
290                ( DeviceHandle, IOCTL_FILE_ATTACH, InBuffer,
291                  sizeof ( InBuffer ), NULL, 0, &BytesReturned,
292                  ( LPOVERLAPPED ) NULL ) )
293             {
294               printf ( "DeviceIoControl (%d)\n", ( int )GetLastError (  ) );
295             }
296           break;
297         }
298       case CommandDetach:
299         sscanf ( argv[2], "%d", ( int * )&Disk );
300         printf ( "Detaching file-backed disk %d\n", ( int )Disk );
301         memcpy ( &InBuffer, &Disk, 4 );
302         if ( !DeviceIoControl
303              ( DeviceHandle, IOCTL_FILE_DETACH, InBuffer, sizeof ( InBuffer ),
304                NULL, 0, &BytesReturned, ( LPOVERLAPPED ) NULL ) )
305           {
306             printf ( "DeviceIoControl (%d)\n", ( int )GetLastError (  ) );
307           }
308         break;
309     }
310   CloseHandle ( DeviceHandle );
311
312 end:
313   return 0;
314 }