ntdll: Win64 printf format warning fixes.
[wine] / dlls / ntdll / tape.c
1 /*
2  * TAPE support
3  *
4  * Copyright 2006 Hans Leidekker
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #ifdef HAVE_SYS_IOCTL_H
27 #include <sys/ioctl.h>
28 #endif
29 #ifdef HAVE_SYS_MTIO_H
30 #include <sys/mtio.h>
31 #endif
32
33 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
34 #define MTCOMPRESSION MTCOMP
35 #endif
36 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
37 #define MTSETBLK MTSETBSIZ
38 #endif
39 #if !defined(MTSETBLK) && defined(MTSRSZ)
40 #define MTSETBLK MTSRSZ
41 #endif
42 #ifndef MT_ST_BLKSIZE_MASK
43 #define MT_ST_BLKSIZE_MASK 0xffffff
44 #endif
45
46 #define NONAMELESSUNION
47 #define NONAMELESSSTRUCT
48 #include "ntstatus.h"
49 #define WIN32_NO_STATUS
50 #include "windef.h"
51 #include "winternl.h"
52 #include "winioctl.h"
53 #include "ddk/ntddtape.h"
54 #include "ntdll_misc.h"
55 #include "wine/server.h"
56 #include "wine/debug.h"
57
58 WINE_DEFAULT_DEBUG_CHANNEL(tape);
59
60 static const char *io2str( DWORD io )
61 {
62     switch (io)
63     {
64 #define X(x)    case (x): return #x;
65     X(IOCTL_TAPE_CHECK_VERIFY);
66     X(IOCTL_TAPE_CREATE_PARTITION);
67     X(IOCTL_TAPE_ERASE);
68     X(IOCTL_TAPE_FIND_NEW_DEVICES);
69     X(IOCTL_TAPE_GET_DRIVE_PARAMS);
70     X(IOCTL_TAPE_GET_MEDIA_PARAMS);
71     X(IOCTL_TAPE_GET_POSITION);
72     X(IOCTL_TAPE_GET_STATUS);
73     X(IOCTL_TAPE_PREPARE);
74     X(IOCTL_TAPE_SET_DRIVE_PARAMS);
75     X(IOCTL_TAPE_SET_MEDIA_PARAMS);
76     X(IOCTL_TAPE_SET_POSITION);
77     X(IOCTL_TAPE_WRITE_MARKS);
78 #undef X
79     default: { static char tmp[32]; sprintf(tmp, "IOCTL_TAPE_%d\n", io); return tmp; }
80     }
81 }
82
83 /******************************************************************
84  *      TAPE_GetStatus
85  */
86 static NTSTATUS TAPE_GetStatus( int error )
87 {
88     if (!error) return STATUS_SUCCESS;
89     return FILE_GetNtStatus();
90 }
91
92 /******************************************************************
93  *      TAPE_CreatePartition
94  */
95 static NTSTATUS TAPE_CreatePartition( int fd, TAPE_CREATE_PARTITION *data )
96 {
97 #ifdef HAVE_SYS_MTIO_H
98     struct mtop cmd;
99
100     TRACE( "fd: %d method: 0x%08x count: 0x%08x size: 0x%08x\n",
101            fd, data->Method, data->Count, data->Size );
102
103     if (data->Count > 1)
104     {
105         WARN( "Creating more than 1 partition is not supported\n" );
106         return STATUS_INVALID_PARAMETER;
107     }
108
109     switch (data->Method)
110     {
111 #ifdef MTMKPART
112     case TAPE_FIXED_PARTITIONS:
113     case TAPE_SELECT_PARTITIONS:
114         cmd.mt_op = MTMKPART;
115         cmd.mt_count = 0;
116         break;
117     case TAPE_INITIATOR_PARTITIONS:
118         cmd.mt_op = MTMKPART;
119         cmd.mt_count = data->Size;
120         break;
121 #endif
122     default:
123         ERR( "Unhandled method: 0x%08x\n", data->Method );
124         return STATUS_INVALID_PARAMETER;
125     }
126
127     return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
128 #else
129     FIXME( "Not implemented.\n" );
130     return STATUS_NOT_SUPPORTED;
131 #endif
132 }
133
134 /******************************************************************
135  *      TAPE_Erase
136  */
137 static NTSTATUS TAPE_Erase( int fd, TAPE_ERASE *data )
138 {
139 #ifdef HAVE_SYS_MTIO_H
140     struct mtop cmd;
141
142     TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
143            fd, data->Type, data->Immediate );
144
145     switch (data->Type)
146     {
147     case TAPE_ERASE_LONG:
148         cmd.mt_op = MTERASE;
149         cmd.mt_count = 1;
150         break;
151     case TAPE_ERASE_SHORT:
152         cmd.mt_op = MTERASE;
153         cmd.mt_count = 0;
154         break;
155     default:
156         ERR( "Unhandled type: 0x%08x\n", data->Type );
157         return STATUS_INVALID_PARAMETER;
158     }
159
160     return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
161 #else
162     FIXME( "Not implemented.\n" );
163     return STATUS_NOT_SUPPORTED;
164 #endif
165 }
166
167 /******************************************************************
168  *      TAPE_GetDriveParams
169  */
170 static NTSTATUS TAPE_GetDriveParams( int fd, TAPE_GET_DRIVE_PARAMETERS *data )
171 {
172 #ifdef HAVE_SYS_MTIO_H
173     struct mtget get;
174     NTSTATUS status;
175
176     TRACE( "fd: %d\n", fd );
177
178     memset( data, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS) );
179
180     status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
181     if (status != STATUS_SUCCESS)
182         return status;
183
184     data->ECC = FALSE;
185     data->Compression = FALSE;
186     data->DataPadding = FALSE;
187     data->ReportSetmarks = FALSE;
188 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
189     data->DefaultBlockSize = get.mt_blksiz;
190 #else
191     data->DefaultBlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
192 #endif
193     data->MaximumBlockSize = data->DefaultBlockSize;
194     data->MinimumBlockSize = data->DefaultBlockSize;
195     data->MaximumPartitionCount = 1;
196
197     return status;
198 #else
199     FIXME( "Not implemented.\n" );
200     return STATUS_NOT_SUPPORTED;
201 #endif
202 }
203
204 /******************************************************************
205  *      TAPE_GetMediaParams
206  */
207 static NTSTATUS TAPE_GetMediaParams( int fd, TAPE_GET_MEDIA_PARAMETERS *data )
208 {
209 #ifdef HAVE_SYS_MTIO_H
210     struct mtget get;
211     NTSTATUS status;
212
213     TRACE( "fd: %d\n", fd );
214
215     memset( data, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS) );
216
217     status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
218     if (status != STATUS_SUCCESS)
219         return status;
220
221     data->Capacity.u.LowPart = 1024 * 1024 * 1024;
222     data->Remaining.u.LowPart = 1024 * 1024 * 1024;
223 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
224     data->BlockSize = get.mt_blksiz;
225 #else
226     data->BlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
227 #endif
228     data->PartitionCount = 1;
229 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
230     data->WriteProtected = GMT_WR_PROT(get.mt_gstat);
231 #else
232     data->WriteProtected = 0;
233 #endif
234
235     return status;
236 #else
237     FIXME( "Not implemented.\n" );
238     return STATUS_NOT_SUPPORTED;
239 #endif
240 }
241
242 /******************************************************************
243  *      TAPE_GetPosition
244  */
245 static NTSTATUS TAPE_GetPosition( int fd, ULONG type, TAPE_GET_POSITION *data )
246 {
247 #ifdef HAVE_SYS_MTIO_H
248     struct mtget get;
249 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
250     struct mtpos pos;
251 #endif
252     NTSTATUS status;
253
254     TRACE( "fd: %d type: 0x%08x\n", fd, type );
255
256     memset( data, 0, sizeof(TAPE_GET_POSITION) );
257
258     status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
259     if (status != STATUS_SUCCESS)
260         return status;
261
262 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
263     status = TAPE_GetStatus( ioctl( fd, MTIOCPOS, &pos ) );
264     if (status != STATUS_SUCCESS)
265         return status;
266 #endif
267
268     switch (type)
269     {
270     case TAPE_ABSOLUTE_BLOCK:
271         data->Type = type;
272         data->Partition = get.mt_resid;
273 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
274         data->OffsetLow = get.mt_blkno;
275 #else
276         data->OffsetLow = pos.mt_blkno;
277 #endif
278         break;
279     case TAPE_LOGICAL_BLOCK:
280     case TAPE_PSEUDO_LOGICAL_BLOCK:
281         WARN( "Positioning type not supported\n" );
282         break;
283     default:
284         ERR( "Unhandled type: 0x%08x\n", type );
285         return STATUS_INVALID_PARAMETER;
286     }
287
288     return status;
289 #else
290     FIXME( "Not implemented.\n" );
291     return STATUS_NOT_SUPPORTED;
292 #endif
293 }
294
295 /******************************************************************
296  *      TAPE_Prepare
297  */
298 static NTSTATUS TAPE_Prepare( int fd, TAPE_PREPARE *data )
299 {
300 #ifdef HAVE_SYS_MTIO_H
301     struct mtop cmd;
302
303     TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
304            fd, data->Operation, data->Immediate );
305
306     switch (data->Operation)
307     {
308 #ifdef MTLOAD
309     case TAPE_LOAD:
310         cmd.mt_op = MTLOAD;
311         break;
312 #endif
313 #ifdef MTUNLOAD
314     case TAPE_UNLOAD:
315         cmd.mt_op = MTUNLOAD;
316         break;
317 #endif
318 #ifdef MTRETEN
319     case TAPE_TENSION:
320         cmd.mt_op = MTRETEN;
321         break;
322 #endif
323 #ifdef MTLOCK
324     case TAPE_LOCK:
325         cmd.mt_op = MTLOCK;
326         break;
327 #endif
328 #ifdef MTUNLOCK
329     case TAPE_UNLOCK:
330         cmd.mt_op = MTUNLOCK;
331         break;
332 #endif
333     case TAPE_FORMAT:
334         /* Native ignores this if the drive doesn't support it */
335         return STATUS_SUCCESS;
336     default:
337         ERR( "Unhandled operation: 0x%08x\n", data->Operation );
338         return STATUS_INVALID_PARAMETER;
339     }
340
341     return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
342 #else
343     FIXME( "Not implemented.\n" );
344     return STATUS_NOT_SUPPORTED;
345 #endif
346 }
347
348 /******************************************************************
349  *      TAPE_SetDriveParams
350  */
351 static NTSTATUS TAPE_SetDriveParams( int fd, TAPE_SET_DRIVE_PARAMETERS *data )
352 {
353 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
354     struct mtop cmd;
355
356     TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
357             fd, data->ECC, data->Compression, data->DataPadding );
358     TRACE( "setmarks: 0x%02x zonesize: 0x%08x\n",
359            data->ReportSetmarks, data->EOTWarningZoneSize );
360
361     if (data->ECC || data->DataPadding || data->ReportSetmarks ||
362         data->EOTWarningZoneSize ) WARN( "Setting not supported\n" );
363
364     cmd.mt_op = MTCOMPRESSION;
365     cmd.mt_count = data->Compression;
366
367     return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
368 #else
369     FIXME( "Not implemented.\n" );
370     return STATUS_NOT_SUPPORTED;
371 #endif
372 }
373         
374 /******************************************************************
375  *      TAPE_SetMediaParams
376  */
377 static NTSTATUS TAPE_SetMediaParams( int fd, TAPE_SET_MEDIA_PARAMETERS *data )
378 {
379 #ifdef HAVE_SYS_MTIO_H
380     struct mtop cmd;
381
382     TRACE( "fd: %d blocksize: 0x%08x\n", fd, data->BlockSize );
383     
384     cmd.mt_op = MTSETBLK;
385     cmd.mt_count = data->BlockSize;
386
387     return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
388 #else
389     FIXME( "Not implemented.\n" );
390     return STATUS_NOT_SUPPORTED;
391 #endif
392 }
393         
394 /******************************************************************
395  *      TAPE_SetPosition
396  */
397 static NTSTATUS TAPE_SetPosition( int fd, TAPE_SET_POSITION *data )
398 {
399 #ifdef HAVE_SYS_MTIO_H
400     struct mtop cmd;
401
402     TRACE( "fd: %d method: 0x%08x partition: 0x%08x offset: 0x%08x immediate: 0x%02x\n",
403            fd, data->Method, data->Partition, data->Offset.u.LowPart, data->Immediate );
404
405     if (data->Offset.u.HighPart > 0)
406         return STATUS_INVALID_PARAMETER;
407
408     switch (data->Method)
409     {
410     case TAPE_REWIND:
411         cmd.mt_op = MTREW;
412         break;
413 #ifdef MTSEEK
414     case TAPE_ABSOLUTE_BLOCK:
415         cmd.mt_op = MTSEEK;
416         cmd.mt_count = data->Offset.u.LowPart;
417         break;
418 #endif
419 #ifdef MTEOM
420     case TAPE_SPACE_END_OF_DATA:
421         cmd.mt_op = MTEOM;
422         break;
423 #endif
424     case TAPE_SPACE_FILEMARKS:
425         if (data->Offset.u.LowPart >= 0) {
426             cmd.mt_op = MTFSF;
427             cmd.mt_count = data->Offset.u.LowPart;
428         }
429         else {
430             cmd.mt_op = MTBSF;
431             cmd.mt_count = -data->Offset.u.LowPart;
432         }
433         break;
434 #if defined(MTFSS) && defined(MTBSS)
435     case TAPE_SPACE_SETMARKS:
436         if (data->Offset.u.LowPart >= 0) {
437             cmd.mt_op = MTFSS;
438             cmd.mt_count = data->Offset.u.LowPart;
439         }
440         else {
441             cmd.mt_op = MTBSS;
442             cmd.mt_count = -data->Offset.u.LowPart;
443         }
444         break;
445 #endif
446     case TAPE_LOGICAL_BLOCK:
447     case TAPE_PSEUDO_LOGICAL_BLOCK:
448     case TAPE_SPACE_RELATIVE_BLOCKS:
449     case TAPE_SPACE_SEQUENTIAL_FMKS:
450     case TAPE_SPACE_SEQUENTIAL_SMKS:
451         WARN( "Positioning method not supported\n" );
452         return STATUS_INVALID_PARAMETER;
453     default:
454         ERR( "Unhandled method: 0x%08x\n", data->Method );
455         return STATUS_INVALID_PARAMETER;
456     }
457
458     return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
459 #else
460     FIXME( "Not implemented.\n" );
461     return STATUS_NOT_SUPPORTED;
462 #endif
463 }
464
465 /******************************************************************
466  *      TAPE_WriteMarks
467  */
468 static NTSTATUS TAPE_WriteMarks( int fd, TAPE_WRITE_MARKS *data )
469 {
470 #ifdef HAVE_SYS_MTIO_H
471     struct mtop cmd;
472
473     TRACE( "fd: %d type: 0x%08x count: 0x%08x immediate: 0x%02x\n",
474            fd, data->Type, data->Count, data->Immediate );
475
476     switch (data->Type)
477     {
478 #ifdef MTWSM
479     case TAPE_SETMARKS:
480         cmd.mt_op = MTWSM;
481         cmd.mt_count = data->Count;
482         break;
483 #endif
484     case TAPE_FILEMARKS:
485     case TAPE_SHORT_FILEMARKS:
486     case TAPE_LONG_FILEMARKS:
487         cmd.mt_op = MTWEOF;
488         cmd.mt_count = data->Count;
489         break;
490     default:
491         ERR( "Unhandled type: 0x%08x\n", data->Type );
492         return STATUS_INVALID_PARAMETER;
493     }
494
495     return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
496 #else
497     FIXME( "Not implemented.\n" );
498     return STATUS_NOT_SUPPORTED;
499 #endif
500 }
501
502 /******************************************************************
503  *              TAPE_DeviceIoControl
504  *
505  * SEE ALSO
506  *   NtDeviceIoControl.
507  */
508 NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
509     PIO_APC_ROUTINE apc, PVOID apc_user, PIO_STATUS_BLOCK io_status,
510     ULONG io_control, LPVOID in_buffer, DWORD in_size,
511     LPVOID out_buffer, DWORD out_size )
512 {
513     DWORD sz = 0;
514     NTSTATUS status = STATUS_INVALID_PARAMETER;
515     int fd;
516
517     TRACE( "%p %s %p %d %p %d %p\n", device, io2str(io_control),
518            in_buffer, in_size, out_buffer, out_size, io_status );
519
520     io_status->Information = 0;
521
522     if ((status = wine_server_handle_to_fd( device, 0, &fd, NULL )))
523         goto error;
524
525     switch (io_control)
526     {
527     case IOCTL_TAPE_CREATE_PARTITION:
528         status = TAPE_CreatePartition( fd, (TAPE_CREATE_PARTITION *)in_buffer );
529         break;
530     case IOCTL_TAPE_ERASE:
531         status = TAPE_Erase( fd, (TAPE_ERASE *)in_buffer );
532         break;
533     case IOCTL_TAPE_GET_DRIVE_PARAMS:
534         status = TAPE_GetDriveParams( fd, (TAPE_GET_DRIVE_PARAMETERS *)out_buffer );
535         break;
536     case IOCTL_TAPE_GET_MEDIA_PARAMS:
537         status = TAPE_GetMediaParams( fd, (TAPE_GET_MEDIA_PARAMETERS *)out_buffer );
538         break;
539     case IOCTL_TAPE_GET_POSITION:
540         status = TAPE_GetPosition( fd, ((TAPE_GET_POSITION *)in_buffer)->Type,
541                                    (TAPE_GET_POSITION *)out_buffer );
542         break;
543     case IOCTL_TAPE_GET_STATUS:
544         status = FILE_GetNtStatus();
545         break;
546     case IOCTL_TAPE_PREPARE:
547         status = TAPE_Prepare( fd, (TAPE_PREPARE *)in_buffer );
548         break;
549     case IOCTL_TAPE_SET_DRIVE_PARAMS:
550         status = TAPE_SetDriveParams( fd, (TAPE_SET_DRIVE_PARAMETERS *)in_buffer );
551         break;
552     case IOCTL_TAPE_SET_MEDIA_PARAMS:
553         status = TAPE_SetMediaParams( fd, (TAPE_SET_MEDIA_PARAMETERS *)in_buffer );
554         break;
555     case IOCTL_TAPE_SET_POSITION:
556         status = TAPE_SetPosition( fd, (TAPE_SET_POSITION *)in_buffer );
557         break;
558     case IOCTL_TAPE_WRITE_MARKS:
559         status = TAPE_WriteMarks( fd, (TAPE_WRITE_MARKS *)in_buffer );
560         break;
561
562     case IOCTL_TAPE_CHECK_VERIFY:
563     case IOCTL_TAPE_FIND_NEW_DEVICES:
564         break;
565     default:
566         FIXME( "Unsupported IOCTL %x (type=%x access=%x func=%x meth=%x)\n",
567                io_control, io_control >> 16, (io_control >> 14) & 3,
568                (io_control >> 2) & 0xfff, io_control & 3 );
569         break;
570     }
571
572     wine_server_release_fd( device, fd );
573
574 error:
575     io_status->u.Status = status;
576     io_status->Information = sz;
577     if (event) NtSetEvent( event, NULL );
578     return status;
579 }