Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:19

0001 /**
0002  * @file
0003  *
0004  * Block device partition management.
0005  */
0006 
0007 /*
0008  * Copyright (c) 2009, 2020
0009  *
0010  * The license and distribution terms for this file may be
0011  * found in the file LICENSE in this distribution or at
0012  * http://www.rtems.org/license/LICENSE.
0013  */
0014 
0015 #ifdef HAVE_CONFIG_H
0016 #include "config.h"
0017 #endif
0018 
0019 #include <stdio.h>
0020 #include <stdlib.h>
0021 #include <string.h>
0022 
0023 #include <rtems/bdpart.h>
0024 #include <rtems/error.h>
0025 #include <rtems/shell.h>
0026 
0027 #define RTEMS_BDPART_SHELL_ERROR( fmt, ...) \
0028   do { \
0029     printf( "error: " fmt "\n", ##__VA_ARGS__); \
0030     return -1; \
0031   } while (0)
0032 
0033 #define RTEMS_BDPART_SHELL_ERROR_SC( sc, fmt, ...) \
0034   if ((sc) != RTEMS_SUCCESSFUL) { \
0035     printf( "error: " fmt ": %s\n", ##__VA_ARGS__, rtems_status_text( sc)); \
0036     return -1; \
0037   }
0038 
0039 typedef enum {
0040   RTEMS_BDPART_SHELL_FS,
0041   RTEMS_BDPART_SHELL_N,
0042   RTEMS_BDPART_SHELL_MBR,
0043   RTEMS_BDPART_SHELL_GPT
0044 } rtems_bdpart_shell_state;
0045 
0046 static const char rtems_bdpart_shell_usage [] =
0047   "disk format and utility functions\n"
0048   "\n"
0049   "fdisk DISK_NAME\n"
0050   "\tprints the partition table\n"
0051   "\n"
0052   "fdisk DISK_NAME [FS N1 [N2 ... ]] ... [write] [FORMAT]\n"
0053   "\tcreates a new partition table\n"
0054   "\n"
0055   "fdisk DISK_NAME register\n"
0056   "\tcreates a logical disk for each partition of the disk\n"
0057   "\n"
0058   "fdisk DISK_NAME unregister\n"
0059   "\tdeletes the logical disks associated with the partitions\n"
0060   "\tof the disk\n"
0061   "\n"
0062   "option values:\n"
0063   "\tDISK_NAME: absolute path to disk device like '/dev/hda'\n"
0064   "\tN*: weights of positive integers\n"
0065   "\tFS: 0x00 ... 0xff, fat12, fat16, fat32, data\n"
0066   "\twrite: write the new partition table to the disk\n"
0067   "\tFORMAT: mbr [[no]dos], gpt";
0068 
0069 static int rtems_bdpart_shell_main( int argc, char **argv)
0070 {
0071   rtems_status_code sc = RTEMS_SUCCESSFUL;
0072   rtems_bdpart_format format;
0073   rtems_bdpart_partition pt [RTEMS_BDPART_PARTITION_NUMBER_HINT];
0074   unsigned dist [RTEMS_BDPART_PARTITION_NUMBER_HINT];
0075   size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
0076   const char *disk_name = NULL;
0077   bool do_create = false;
0078   bool do_read = false;
0079   bool do_write = false;
0080   bool do_register = false;
0081   bool do_unregister = false;
0082   bool do_dump = false;
0083 
0084   if (argc < 2) {
0085     puts( rtems_bdpart_shell_usage);
0086     return -1;
0087   }
0088 
0089   disk_name = argv [1];
0090 
0091   if (argc == 2) {
0092     do_read = true;
0093     do_dump = true;
0094   } else if (argc == 3) {
0095     /* Check option */
0096     if (strcmp( argv [2], "register") == 0) {
0097       do_read = true;
0098       do_register = true;
0099     } else if (strcmp( argv [2], "unregister") == 0) {
0100       do_read = true;
0101       do_unregister = true;
0102     } else {
0103       RTEMS_BDPART_SHELL_ERROR( "unexpected option: %s", argv [2]);
0104     }
0105   } else {
0106     rtems_bdpart_shell_state state = RTEMS_BDPART_SHELL_FS;
0107     uint8_t current_type = RTEMS_BDPART_MBR_FAT_32;
0108     size_t i = 0;
0109     int ai = 0;
0110 
0111     /* Clear partition table */
0112     memset( pt, 0, sizeof( pt));
0113 
0114     /* Default format */
0115     format.type = RTEMS_BDPART_FORMAT_MBR;
0116     format.mbr.disk_id = 0;
0117     format.mbr.dos_compatibility = true;
0118 
0119     for (ai = 2; ai < argc; ++ai) {
0120       char *s = argv [ai];
0121       unsigned long v = 0;
0122       char *end = NULL;
0123 
0124       if (strlen( s) == 0) {
0125         continue;
0126       } else if (strcmp( s, "write") == 0) {
0127         do_write = true;
0128         continue;
0129       } else if (strcmp( s, "mbr") == 0) {
0130         state = RTEMS_BDPART_SHELL_MBR;
0131         format.type = RTEMS_BDPART_FORMAT_MBR;
0132         continue;
0133       } else if (strcmp( s, "gpt") == 0) {
0134         state = RTEMS_BDPART_SHELL_GPT;
0135         format.type = RTEMS_BDPART_FORMAT_GPT;
0136         continue;
0137       }
0138 
0139       switch (state) {
0140         case RTEMS_BDPART_SHELL_FS:
0141           v = strtoul( s, &end, 16);
0142           if (*end == '\0') {
0143             if (v <= 0xffU) {
0144               current_type = (uint8_t) v;
0145             } else {
0146               RTEMS_BDPART_SHELL_ERROR( "type value out of range: %s", argv [ai]);
0147             }
0148           } else if (strcmp( s, "fat32") == 0) {
0149             current_type = RTEMS_BDPART_MBR_FAT_32;
0150           } else if (strcmp( s, "data") == 0) {
0151             current_type = RTEMS_BDPART_MBR_DATA;
0152           } else if (strcmp( s, "fat16") == 0) {
0153             current_type = RTEMS_BDPART_MBR_FAT_16;
0154           } else if (strcmp( s, "fat12") == 0) {
0155             current_type = RTEMS_BDPART_MBR_FAT_12;
0156           } else {
0157             RTEMS_BDPART_SHELL_ERROR( "unexpected option: %s", argv [ai]);
0158           }
0159           state = RTEMS_BDPART_SHELL_N;
0160           break;
0161         case RTEMS_BDPART_SHELL_N:
0162           v = strtoul( s, &end, 10);
0163           if (*end == '\0') {
0164             rtems_bdpart_to_partition_type( current_type, pt [i].type);
0165             dist [i] = v;
0166             if (i < count) {
0167               ++i;
0168             } else {
0169               RTEMS_BDPART_SHELL_ERROR( "too many partitions");
0170             }
0171           } else {
0172             --ai;
0173             state = RTEMS_BDPART_SHELL_FS;
0174           }
0175           break;
0176         case RTEMS_BDPART_SHELL_MBR:
0177           if (strcmp( s, "dos") == 0) {
0178             format.mbr.dos_compatibility = true;
0179           } else if (strcmp( s, "nodos") == 0) {
0180             format.mbr.dos_compatibility = false;
0181           } else {
0182             RTEMS_BDPART_SHELL_ERROR( "unexpected option: %s", argv [ai]);
0183           }
0184           break;
0185         case RTEMS_BDPART_SHELL_GPT:
0186           RTEMS_BDPART_SHELL_ERROR( "unexpected option: %s", argv [ai]);
0187         default:
0188           RTEMS_BDPART_SHELL_ERROR( "fdisk interal error");
0189       }
0190     }
0191 
0192     /* Partition number */
0193     count = i;
0194 
0195     /* Actions */
0196     do_create = true;
0197     do_dump = true;
0198     if (do_write) {
0199       do_read = true;
0200     }
0201   }
0202 
0203   if (do_create) {
0204     /* Create partitions */
0205     sc = rtems_bdpart_create( disk_name, &format, pt, dist, count);
0206     RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot create partitions for '%s'", disk_name);
0207   }
0208 
0209   if (do_write) {
0210     /* Write partitions */
0211     sc = rtems_bdpart_write( disk_name, &format, pt, count);
0212     RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot write partitions to '%s'", disk_name);
0213   }
0214 
0215   if (do_read) {
0216     /* Read partitions */
0217     count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
0218     sc = rtems_bdpart_read( disk_name, &format, pt, &count);
0219     RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot read partitions from '%s'", disk_name);
0220   }
0221 
0222   if (do_register) {
0223     /* Register partitions */
0224     sc = rtems_bdpart_register( disk_name, pt, count);
0225     RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot register partitions of '%s'", disk_name);
0226   }
0227 
0228   if (do_unregister) {
0229     /* Unregister partitions */
0230     sc = rtems_bdpart_unregister( disk_name, pt, count);
0231     RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot unregister partitions of '%s'", disk_name);
0232   }
0233 
0234   if (do_dump) {
0235     /* Dump partitions */
0236     rtems_bdpart_dump( pt, count);
0237   }
0238 
0239   return 0;
0240 }
0241 
0242 struct rtems_shell_cmd_tt rtems_shell_FDISK_Command = {
0243   .name = "fdisk",
0244   .usage = rtems_bdpart_shell_usage,
0245   .topic = "files",
0246   .command = rtems_bdpart_shell_main,
0247   .alias = NULL,
0248   .next = NULL
0249 };