Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring External Dependencies Using Unix System Calls into Libraries #622

Open
Knogle opened this issue Oct 25, 2024 · 1 comment
Open

Comments

@Knogle
Copy link
Contributor

Knogle commented Oct 25, 2024

Ahoy! As I’m spending the week in the hospital undergoing a series of tests to investigate some allergic reactions, I’ve got a bit of time and thought it might be a good opportunity to work on a project.

I’ve been considering ways to streamline dependency management for certain Linux programs that typically rely on calling external binaries and parsing their outputs. Instead of depending on these binaries, I’m thinking of refactoring them into shared or static libraries, which could simplify interactions and reduce external system calls and syntax.

I've already managed to do this with the NIST-Suite, and I believe it might also be possible for other utilities, such as hdparm, by creating a forked version that’s repurposed as a library.

Do you think this approach could be beneficial? If not, I’d appreciate any input or suggestions for other productive ideas—just looking to make good use of the week!

@Knogle
Copy link
Contributor Author

Knogle commented Oct 29, 2024

Done!

HDParm Library

HDParm Logo

Table of Contents

  1. Introduction
  2. Features
  3. Installation
  4. Usage
  5. API Documentation
  6. Examples
  7. Error Handling
  8. Contributing
  9. License
  10. Acknowledgements
  11. Contact

Introduction

HDParm Library is a powerful C library designed to provide low-level access and control over hard disk drives (HDDs) and solid-state drives (SSDs) on Linux systems. Inspired by the popular hdparm utility, this library allows developers to integrate drive configuration, optimization, and management functionalities directly into their C applications.

Whether you're developing system utilities, monitoring tools, or custom drive management software, HDParm Library offers a comprehensive set of functions to interact with storage devices at a granular level.

Features

  • Drive Identification: Retrieve detailed information about HDDs and SSDs, including model name, firmware version, serial number, and supported features.
  • Drive Configuration: Adjust drive settings such as PIO/DMA modes, read-ahead buffers, and acoustic management.
  • Caching Operations: Flush the drive's write cache to ensure data integrity.
  • Security Management: Set, unlock, disable, and erase security passwords on drives.
  • Sanitization: Perform secure erase operations to permanently remove all data from drives.
  • Error Handling: Comprehensive error codes and messages for robust application development.
  • Extensible API: Modular design allows for easy extension and integration into various applications.

Installation

Prerequisites

  • C Compiler: GCC or any other C99-compatible compiler.
  • Linux System: The library is designed for Linux environments.
  • Development Headers: Ensure that development headers for SCSI Generic (SG) and other necessary interfaces are installed.

Building the Library

  1. Clone the Repository:

    git clone https://github.com/yourusername/hdparm-library.git
    cd hdparm-library
  2. Compile the Library:

    As a Shared Library (libhdparm.so):

    gcc -fPIC -c hdparm_lib.c -o hdparm_lib.o
    gcc -shared -o libhdparm.so hdparm_lib.o

    As a Static Library (libhdparm.a):

    gcc -c hdparm_lib.c -o hdparm_lib.o
    ar rcs libhdparm.a hdparm_lib.o
  3. Install the Library:

    For Shared Libraries:

    sudo cp libhdparm.so /usr/local/lib/
    sudo ldconfig

    For Static Libraries:

    sudo cp libhdparm.a /usr/local/lib/
  4. Include Header Files:

    sudo cp hdparm_lib.h /usr/local/include/

Usage

Including the Library

In your C program, include the HDParm Library header:

#include "hdparm_lib.h"

Linking the Library

When compiling your program, link against the HDParm Library:

For Shared Libraries:

gcc your_program.c -L/usr/local/lib -lhdparm -o your_program

For Static Libraries:

gcc your_program.c -L/usr/local/lib -lhdparm -o your_program

Ensure that the library path (/usr/local/lib in this example) is correctly specified based on where you installed the library.

API Documentation

Initialization and Cleanup

int hdparm_init();

Initializes the HDParm Library. Call this function before using any other library functions.

  • Returns:
    • HPARM_SUCCESS on success.
    • Relevant error code on failure.

int hdparm_cleanup();

Performs any necessary cleanup before the application exits.

  • Returns:
    • HPARM_SUCCESS on success.
    • Relevant error code on failure.

Drive Identification

int hdparm_get_identify_data(const char *device, uint16_t *identify_data);

Retrieves the identification data from the specified drive.

  • Parameters:

    • device: Path to the device (e.g., /dev/sda).
    • identify_data: Pointer to a buffer where the identification data will be stored (must be at least 256 uint16_t elements).
  • Returns:

    • HPARM_SUCCESS on success.
    • Relevant error code on failure.

int hdparm_display_identity(const uint16_t *identify_data);

Parses and displays the identification data in a human-readable format.

  • Parameters:

    • identify_data: Pointer to the identification data buffer.
  • Returns:

    • HPARM_SUCCESS on success.
    • HPARM_ERR_INVALID_ARG if the identification data is invalid.

Drive Configuration

int hdparm_set_pio_mode(const char *device, int mode);

Sets the PIO mode of the specified drive.

  • Parameters:

    • device: Path to the device.
    • mode: PIO mode to set (e.g., 0 for automatic tuning).
  • Returns:

    • HPARM_SUCCESS on success.
    • Relevant error code on failure.

int hdparm_set_dma_mode(const char *device, int mode);

Sets the DMA mode of the specified drive.

  • Parameters:

    • device: Path to the device.
    • mode: DMA mode to set.
  • Returns:

    • HPARM_SUCCESS on success.
    • Relevant error code on failure.

Caching Operations

int hdparm_flush_write_cache(const char *device);

Flushes the write cache of the specified drive to ensure all buffered data is written to the disk.

  • Parameters:

    • device: Path to the device.
  • Returns:

    • HPARM_SUCCESS on success.
    • Relevant error code on failure.

Security Management

int hdparm_secure_erase(const char *device, const char *password);

Performs a secure erase on the specified drive using the provided password.

  • Parameters:

    • device: Path to the device.
    • password: Security password set on the drive.
  • Returns:

    • HPARM_SUCCESS on success.
    • Relevant error code on failure.

Sanitization

int hdparm_sanitize_drive(const char *device, sanitize_type_t type);

Performs a sanitization operation on the specified drive.

  • Parameters:

    • device: Path to the device.
    • type: Type of sanitization (e.g., SANITIZE_OVERWRITE, SANITIZE_ERASE).
  • Returns:

    • HPARM_SUCCESS on success.
    • Relevant error code on failure.

Note: Define sanitize_type_t as per your implementation requirements.

Examples

Retrieving Drive Identification

#include <stdio.h>
#include "hdparm_lib.h"

int main() {
    int ret;
    uint16_t identify_data[256];

    ret = hdparm_init();
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to initialize HDParm Library.\n");
        return ret;
    }

    ret = hdparm_get_identify_data("/dev/sda", identify_data);
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to get identify data.\n");
        return ret;
    }

    ret = hdparm_display_identity(identify_data);
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to display identify data.\n");
        return ret;
    }

    ret = hdparm_cleanup();
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to cleanup HDParm Library.\n");
        return ret;
    }

    return 0;
}

Flushing Write Cache

#include <stdio.h>
#include "hdparm_lib.h"

int main() {
    int ret;

    ret = hdparm_init();
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to initialize HDParm Library.\n");
        return ret;
    }

    ret = hdparm_flush_write_cache("/dev/sda");
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to flush write cache.\n");
        return ret;
    }

    printf("Write cache flushed successfully.\n");

    ret = hdparm_cleanup();
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to cleanup HDParm Library.\n");
        return ret;
    }

    return 0;
}

Performing a Secure Erase

#include <stdio.h>
#include "hdparm_lib.h"

int main() {
    int ret;
    const char *password = "securepassword";

    ret = hdparm_init();
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to initialize HDParm Library.\n");
        return ret;
    }

    ret = hdparm_secure_erase("/dev/sda", password);
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to perform secure erase.\n");
        return ret;
    }

    printf("Secure erase completed successfully.\n");

    ret = hdparm_cleanup();
    if (ret != HDPARM_SUCCESS) {
        fprintf(stderr, "Failed to cleanup HDParm Library.\n");
        return ret;
    }

    return 0;
}

Error Handling

All functions in the HDParm Library return predefined error codes. It's essential to handle these errors gracefully in your application to ensure reliability and provide meaningful feedback to users.

Error Codes:

  • HPARM_SUCCESS (0): Operation completed successfully.
  • HPARM_ERR_OPEN (1): Failed to open the specified device.
  • HPARM_ERR_IOCTL (2): An ioctl operation failed.
  • HPARM_ERR_MEMORY (3): Memory allocation failed.
  • HPARM_ERR_INVALID_ARG (4): Invalid argument provided to a function.
  • HPARM_ERR_COMMAND (5): Failed to execute a specific drive command.
  • HPARM_ERR_UNKNOWN (99): An unknown error occurred.

Usage Example:

int ret = hdparm_flush_write_cache("/dev/sda");
if (ret != HDPARM_SUCCESS) {
    switch (ret) {
        case HDPARM_ERR_OPEN:
            fprintf(stderr, "Error: Unable to open the device.\n");
            break;
        case HDPARM_ERR_IOCTL:
            fprintf(stderr, "Error: Ioctl operation failed.\n");
            break;
        // Handle other error codes as needed
        default:
            fprintf(stderr, "Error: Unknown error occurred.\n");
    }
    // Handle the error accordingly
}

Contributing

Contributions are welcome! If you'd like to improve the HDParm Library, please follow these guidelines:

  1. Fork the Repository: Create a personal copy of the repository on GitHub.

  2. Create a Branch: Make a new branch for your feature or bug fix.

    git checkout -b feature/your-feature-name
  3. Make Changes: Implement your feature or fix.

  4. Commit Changes: Write clear and concise commit messages.

    git commit -m "Add feature X that does Y"
  5. Push to Branch: Push your changes to your forked repository.

    git push origin feature/your-feature-name
  6. Open a Pull Request: Submit a pull request detailing your changes and the motivation behind them.

  7. Respond to Feedback: Collaborate with the maintainers to refine your contribution.

Guidelines:

  • Code Quality: Ensure your code adheres to the project's coding standards and is well-documented.
  • Testing: Include tests for new features or bug fixes to ensure reliability.
  • Documentation: Update the README and other relevant documentation to reflect your changes.
  • Respect Licensing: Ensure your contributions comply with the project's licensing terms.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Acknowledgements

  • Inspired by the hdparm utility.
  • Thanks to the open-source community for providing invaluable resources and support.
  • Only intended for nwipe

Disclaimer: This library provides low-level access to storage devices, which can lead to data loss or hardware damage if used improperly. Always ensure you have backups and understand the implications of the operations you perform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant