Tito sent in a few patches converting instances of CONFIG_FEATURE_CLEAN_UP to
[oweals/busybox.git] / util-linux / fdformat.c
1 /* fdformat.c  -  Low-level formats a floppy disk - Werner Almesberger */
2
3 /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
4  * - added Native Language Support
5  * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
6  * - more i18n/nls translatable strings marked
7  *
8  * 5 July 2003 -- modified for Busybox by Erik Andersen
9  */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <sys/stat.h>
18 #include <sys/ioctl.h>
19 #include "busybox.h"
20
21
22 /* Stuff extracted from linux/fd.h */
23 struct floppy_struct {
24         unsigned int    size,           /* nr of sectors total */
25                         sect,           /* sectors per track */
26                         head,           /* nr of heads */
27                         track,          /* nr of tracks */
28                         stretch;        /* !=0 means double track steps */
29 #define FD_STRETCH 1
30 #define FD_SWAPSIDES 2
31
32         unsigned char   gap,            /* gap1 size */
33
34                         rate,           /* data rate. |= 0x40 for perpendicular */
35 #define FD_2M 0x4
36 #define FD_SIZECODEMASK 0x38
37 #define FD_SIZECODE(floppy) (((((floppy)->rate&FD_SIZECODEMASK)>> 3)+ 2) %8)
38 #define FD_SECTSIZE(floppy) ( (floppy)->rate & FD_2M ? \
39                              512 : 128 << FD_SIZECODE(floppy) )
40 #define FD_PERP 0x40
41
42                         spec1,          /* stepping rate, head unload time */
43                         fmt_gap;        /* gap2 size */
44         const char      * name; /* used only for predefined formats */
45 };
46 struct format_descr {
47         unsigned int device,head,track;
48 };
49 #define FDFMTBEG _IO(2,0x47)
50 #define FDFMTTRK _IOW(2,0x48, struct format_descr)
51 #define FDFMTEND _IO(2,0x49)
52 #define FDGETPRM _IOR(2, 0x04, struct floppy_struct)
53 #define FD_FILL_BYTE 0xF6 /* format fill byte. */
54
55 static void print_and_flush(const char * __restrict format, ...)
56 {
57         va_list arg;
58
59         va_start(arg, format);
60         bb_vfprintf(stdout, format, arg);
61         va_end(arg);
62         bb_xfflush_stdout();
63 }
64
65 static void bb_xioctl(int fd, int request, void *argp, const char *string)
66 {
67         if (ioctl (fd, request, argp) < 0) {
68                 bb_perror_msg_and_die(string);
69         }
70 }
71
72 int fdformat_main(int argc,char **argv)
73 {
74         int fd, n, cyl, read_bytes, verify;
75         unsigned char *data;
76         struct stat st;
77         struct floppy_struct param;
78         struct format_descr descr;
79
80         if (argc < 2) {
81                 bb_show_usage();
82         }
83         verify = !bb_getopt_ulflags(argc, argv, "n");
84         argv += optind;
85
86         /* R_OK is needed for verifying */
87         if (stat(*argv,&st) < 0 || access(*argv,W_OK | R_OK ) < 0) {
88                 bb_perror_msg_and_die(*argv);
89         }
90         if (!S_ISBLK(st.st_mode)) {
91                 bb_error_msg_and_die("%s: not a block device",*argv);
92                 /* do not test major - perhaps this was an USB floppy */
93         }
94
95
96         /* O_RDWR for formatting and verifying */
97         fd = bb_xopen(*argv,O_RDWR );
98
99         bb_xioctl(fd, FDGETPRM, &param, "FDGETPRM");/*original message was: "Could not determine current format type" */
100
101         print_and_flush("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n",
102                 (param.head == 2) ? "Double" : "Single",
103                 param.track, param.sect, param.size >> 1);
104
105         /* FORMAT */
106         print_and_flush("Formatting ... ", NULL);
107         bb_xioctl(fd, FDFMTBEG,NULL,"FDFMTBEG");
108
109         /* n == track */
110         for (n = 0; n < param.track; n++)
111         {
112             descr.head = 0;
113             descr.track = n;
114             bb_xioctl(fd, FDFMTTRK,&descr,"FDFMTTRK");
115             print_and_flush("%3d\b\b\b", n);
116             if (param.head == 2) {
117                 descr.head = 1;
118                 bb_xioctl(fd, FDFMTTRK,&descr,"FDFMTTRK");
119             }
120         }
121
122         bb_xioctl(fd,FDFMTEND,NULL,"FDFMTEND");
123         print_and_flush("done\n", NULL);
124
125         /* VERIFY */
126         if(verify) {
127                 /* n == cyl_size */
128                 n = param.sect*param.head*512;
129
130                 data = xmalloc(n);
131                 print_and_flush("Verifying ... ", NULL);
132                 for (cyl = 0; cyl < param.track; cyl++) {
133                         print_and_flush("%3d\b\b\b", cyl);
134                         if((read_bytes = safe_read(fd,data,n))!= n ) {
135                                 if(read_bytes < 0) {
136                                         bb_perror_msg("Read: ");
137                         }
138                                 bb_error_msg_and_die("Problem reading cylinder %d, expected %d, read %d", cyl, n, read_bytes);
139                         }
140                         /* Check backwards so we don't need a counter */
141                         while(--read_bytes>=0) {
142                                 if( data[read_bytes] != FD_FILL_BYTE) {
143                                          print_and_flush("bad data in cyl %d\nContinuing ... ",cyl);
144                                 }
145                         }
146                 }
147                 /* There is no point in freeing blocks at the end of a program, because
148                 all of the program's space is given back to the system when the process
149                 terminates.*/
150                 
151                 if (ENABLE_FEATURE_CLEAN_UP) free(data);
152                 
153                 print_and_flush("done\n", NULL);
154         }
155
156         if (ENABLE_FEATURE_CLEAN_UP) close(fd);
157         
158         /* Don't bother closing.  Exit does
159          * that, so we can save a few bytes */
160         return EXIT_SUCCESS;
161 }