summaryrefslogtreecommitdiff
path: root/src/hdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hdio.c')
-rw-r--r--src/hdio.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/hdio.c b/src/hdio.c
new file mode 100644
index 000000000..085192183
--- /dev/null
+++ b/src/hdio.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2009, 2010 Jeff Mahoney <jeffm@suse.com>
+ * Copyright (c) 2011-2016 Dmitry V. Levin <ldv@strace.io>
+ * Copyright (c) 2016-2020 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "defs.h"
+
+#include DEF_MPERS_TYPE(struct_hd_geometry)
+
+#include <linux/hdreg.h>
+
+typedef struct hd_geometry struct_hd_geometry;
+
+#include MPERS_DEFS
+
+#include "xlat/hdio_drive_cmds.h"
+
+static int
+print_hdio_getgeo(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ if (entering(tcp)) {
+ tprints(", ");
+
+ return 0;
+ }
+
+ /* exiting */
+ struct_hd_geometry geo;
+
+ if (umove_or_printaddr(tcp, arg, &geo))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(geo, heads);
+ tprint_struct_next();
+ PRINT_FIELD_U(geo, sectors);
+ tprint_struct_next();
+ PRINT_FIELD_U(geo, cylinders);
+ tprint_struct_next();
+ PRINT_FIELD_U(geo, start);
+ tprint_struct_end();
+
+ return RVAL_IOCTL_DECODED;
+}
+
+static int
+print_hdio_drive_cmd(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ enum { SECTOR_SIZE = 512 };
+
+ struct hd_drive_cmd_hdr c;
+
+ if (entering(tcp)) {
+ tprints(", ");
+
+ if (umove_or_printaddr(tcp, arg, &c))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_struct_begin();
+ PRINT_FIELD_XVAL(c, command, hdio_drive_cmds,
+ "ATA_CMD_???");
+ tprint_struct_next();
+ PRINT_FIELD_U(c, sector_number);
+ tprint_struct_next();
+ PRINT_FIELD_U(c, feature);
+ tprint_struct_next();
+ PRINT_FIELD_U(c, sector_count);
+ tprint_struct_end();
+
+ return 0;
+ }
+
+ /* exiting */
+ if ((syserror(tcp) && tcp->u_error != EIO) || umove(tcp, arg, &c))
+ return RVAL_IOCTL_DECODED;
+
+ tprint_value_changed();
+ tprint_struct_begin();
+
+ tprintf("/* status */ %#x, /* error */ %u, /* nsector */ %u",
+ c.command, c.sector_number, c.feature);
+
+ if (c.sector_count) {
+ tprints(", ");
+ printstr_ex(tcp, arg + 4, c.sector_count * SECTOR_SIZE,
+ QUOTE_FORCE_HEX);
+ }
+
+ tprint_struct_end();
+
+ return RVAL_IOCTL_DECODED;
+}
+
+MPERS_PRINTER_DECL(int, hdio_ioctl, struct tcb *const tcp,
+ const unsigned int code, const kernel_ulong_t arg)
+{
+ switch (code) {
+ case HDIO_GETGEO:
+ return print_hdio_getgeo(tcp, arg);
+ case HDIO_DRIVE_CMD:
+ return print_hdio_drive_cmd(tcp, arg);
+ default:
+ return RVAL_DECODED;
+ }
+
+ return RVAL_IOCTL_DECODED;
+}