⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
字号:
/* * The Sleuth Kit *  * Brian Carrier [carrier <at> sleuthkit [dot] org] * Copyright (c) 2005 Brian Carrier.  All rights reserved  * * Based on code from http://www.win.tue.nl/~aeb/linux/setmax.c * and from hdparm * * This software is distributed under the Common Public License 1.0 *//** \file ide.c * Contains the functions to query and configure Linux ATA devices. *//* setmax.c - aeb, 000326 - use on 2.4.0test9 or newer *//* IBM part thanks to Matan Ziv-Av <matan@svgalib.org> */#include "libtsk.h"#if HAVE_CONFIG_H#include "tsk_config.h"#endif#if HAVE_LINUX_HDREG_H#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <fcntl.h>#include <linux/hdreg.h>#include <string.h>#include "disk_ide.h"/** * Get basic information about a device (including the maximum user sector of the drive).   * @param di Structure with info about device * @returns 1 on error and 0 on success */static intidentify_device(DISK_INFO * di){    unsigned char id_args[4 + 512];    uint16_t *id_val;    /* Execute the IDENTIFY DEVICE command */    memset(id_args, 0, 516);    id_args[0] = WIN_IDENTIFY;    id_args[3] = 1;    if (ioctl(di->fd, HDIO_DRIVE_CMD, &id_args)) {        id_args[0] = WIN_PIDENTIFY;        if (ioctl(di->fd, HDIO_DRIVE_CMD, &id_args)) {            fprintf(stderr, "IDENTIFY DEVICE failed\n");            return 1;        }    }    /* The result is organized by 16-bit words */    id_val = (uint16_t *) & id_args[4];    if (id_val[0] & 0x8000) {        fprintf(stderr, "Device is not an ATA disk\n");        return 1;    }    /* Give up if LBA or HPA is not supported */    if ((id_val[49] & 0x0200) == 0) {        fprintf(stderr, "Error: LBA mode not supported by drive\n");        return 1;    }    // see if the removable media feature is supported    if (id_val[82] & 0x0004) {        di->flags |= DISK_HAS_REMOVABLE_SUPPORT;    }    // see if the HPA commands are supported    if (id_val[82] & 0x0400) {        di->flags |= DISK_HAS_HPA_SUPPORT;    }    // see if word 83 is valid -- this is a signature check    if ((id_val[83] & 0xc000) == 0x4000) {        // see if the 48-bit commands are supported        if (id_val[83] & 0x0400) {            di->flags |= DISK_HAS_48_SUPPORT;        }    }    di->user_max = 0;    if (di->flags & DISK_HAS_48_SUPPORT) {        di->user_max = (uint64_t) id_val[103] << 48 |            (uint64_t) id_val[102] << 32 |            (uint64_t) id_val[101] << 16 | (uint64_t) id_val[100];        // the max LBA+1 is in id_val        di->user_max--;    }    /* Use the 28-bit fields */    if (di->user_max == 0) {        di->user_max = (uint64_t) id_val[61] << 16 | id_val[60];        // the max LBA+1 is in id_val        di->user_max--;    }    return 0;}/** * Get the maximum address of the drive (includes the HPA) and set it in * di. * @param di Structure to store native max address in * @returns 1 on error and 0 on success */static intget_native_max(DISK_INFO * di){    unsigned char task_args[7];    int i;    di->native_max = 0;    if ((di->flags & DISK_HAS_HPA_SUPPORT) == 0) {        di->native_max = di->user_max;        return 0;    }    // @@@ check if "Removable feature set is implemented"     // -- according to spec, this command will not work in that case    if (di->flags & DISK_HAS_REMOVABLE_SUPPORT) {        fprintf(stderr, "Removable feature set enabled\n");        di->native_max = di->user_max;        return 0;    }    /* Get the actual size using READ NATIVE MAX ADDRESS */    task_args[0] = WIN_READ_NATIVE_MAX;    task_args[1] = 0x00;    task_args[2] = 0x00;    task_args[3] = 0x00;    task_args[4] = 0x00;    task_args[5] = 0x00;    task_args[6] = 0x40;    if (ioctl(di->fd, HDIO_DRIVE_TASK, &task_args)) {        fprintf(stderr, "READ NATIVE MAX ADDRESS failed\n");        for (i = 0; i < 7; i++)            fprintf(stderr, "%d = 0x%x\n", i, task_args[i]);        return 1;    }    di->native_max = ((task_args[IDE_SELECT_OFFSET] & 0xf) << 24) +        (task_args[IDE_HCYL_OFFSET] << 16) +        (task_args[IDE_LCYL_OFFSET] << 8) + task_args[IDE_SECTOR_OFFSET];    /* @@@ Do the 48-bit version */    if (di->native_max == 0x0fffffff) {        if ((di->flags & DISK_HAS_48_SUPPORT) == 0) {            fprintf(stderr,                "READ NATIVE MAX returned 0xffffff, and 48-bit not supported\n");            return 1;        }        /*           fprintf(stderr,           "This disk uses the 48-bit ATA commands, which are not supported\n");           exit(1);         */#if HAVE_IDE_TASK_REQUEST_T        // Try READ NATIVE MAX ADDRESS EXT        ide_task_request_t req_task;        memset(&req_task, 0, sizeof(req_task));        req_task.io_ports[IDE_SELECT_OFFSET] = 0x40;        req_task.io_ports[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT;        req_task.req_cmd = IDE_DRIVE_TASK_NO_DATA;        req_task.in_flags.all = 0xffff;        if (ioctl(di->fd, HDIO_DRIVE_TASKFILE, &req_task)) {            fprintf(stderr, "READ NATIVE MAX ADDRESS EXT failed\n");            for (i = 0; i < 8; i++)                fprintf(stderr, "%d = 0x%x\n", i, req_task.io_ports[i]);            return 1;        }        /* if OK, compute maximum address value */        if ((req_task.io_ports[IDE_STATUS_OFFSET] & 0x01) == 0) {            uint32_t high = (req_task.hob_ports[IDE_HCYL_OFFSET] << 16) |                (req_task.hob_ports[IDE_LCYL_OFFSET] << 8) |                req_task.hob_ports[IDE_SECTOR_OFFSET];            uint32_t low = ((req_task.io_ports[IDE_HCYL_OFFSET]) << 16) |                ((req_task.io_ports[IDE_LCYL_OFFSET]) << 8) |                (req_task.io_ports[IDE_SECTOR_OFFSET]);            di->native_max = ((uint64_t) high << 24) | low;            di->native_max++;   /* since the return value is (maxlba - 1), we add 1 */        }        else {        }#endif    }    return 0;}/** * Set the maximum user accessible sector. * @param fd Handle to open device * @param addr Maximum address */voidset_max(int fd, uint64_t addr){    unsigned char task_args[7];    uint64_t tmp_size;    int i;    /* Does this require the EXT version? */    if (addr > 0x0fffffff) {        // @@@ Need EXT version        fprintf(stderr,            "This disk requires the 48-bit commands, which are not yet supported\n");        exit(1);    }    else {        /* Now we reset the max address to nat_size */        task_args[0] = 0xf9;        task_args[1] = 0;        task_args[2] = 0;       // Make it temporary        /* Convert the LBA address to the proper register location */        tmp_size = addr;        task_args[3] = (tmp_size & 0xff);        tmp_size >>= 8;        task_args[4] = (tmp_size & 0xff);        tmp_size >>= 8;        task_args[5] = (tmp_size & 0xff);        tmp_size >>= 8;        task_args[6] = (tmp_size & 0x0f);        task_args[6] |= 0x40;   /* Set the LBA mode */        if (ioctl(fd, HDIO_DRIVE_TASK, &task_args)) {            fprintf(stderr, "SET MAX failed\n");            for (i = 0; i < 7; i++)                fprintf(stderr, "%d = 0x%x\n", i, task_args[i]);            exit(1);        }    }} /** * Open the device and collect basic stats on the size * @param a_fd Handle to device * @returns structure with stats or NULL on error */DISK_INFO *device_open(int a_fd){    DISK_INFO *di;    di = (DISK_INFO *) malloc(sizeof(DISK_INFO));    if (di == NULL) {        fprintf(stderr, "Error allocating memory\n");        return NULL;    }    memset(di, 0, sizeof(DISK_INFO));    di->fd = a_fd;    if (identify_device(di)) {        free(di);        return NULL;    }    if (get_native_max(di)) {        free(di);        return NULL;    }    return di;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -