/****************************************************************************** * This little utility, which I call CreateManyPartitions, creates a bunch of * partitions on a disk device. They are just temporary partitions, as they * are not described in the partition table. The advantage of not trying to * be permanent, is that you can have as many as you want. * * By Alexander G. M. Smith, April 2001. Released to the public domain. */ #include #include #include #include #include #include int main (int argc, char** argv) { char CommandString [PATH_MAX]; off_t CylinderSize; int DeviceFile = -1; device_geometry DeviceGeometry; char *DevicePath; off_t DeviceSize; int DoFormat; int NumPartitions; char PartitionDirectory [PATH_MAX]; int PartitionFile = -1; int PartitionIndex; partition_info PartitionInfo; char *PartitionNamePntr; off_t PartitionSize; int ReturnCode = -20; if (argc < 4) { printf ("\nUsage: %s DevicePath NumPartitions PartitionSize " "Format\n\n", argv[0]); printf ("This creates NumPartitions quantity of disk partitions\n"); printf ("each with size PartitionSize in bytes rounded up to\n"); printf ("the next cylinder size multiple. DevicePath is the\n"); printf ("path name of the raw device to use. It will also\n"); printf ("mount the partitions, optionally formatting them with\n"); printf ("the BFS file system if you asked for it.\n\nExamples:\n\n"); printf ("CreateManyPartitions /dev/disk/floppy/raw 3 300000\n"); printf ("CreateManyPartitions " "/dev/disk/virtual/AGMSRAMDiskDevice/raw 30 2000000 format\n\n"); printf ("By Alexander G. M. Smith, April 2001.\n"); goto ErrorExit; } DevicePath = argv[1]; NumPartitions = atoi (argv[2]); PartitionSize = atoll (argv[3]); /* A 64 bit number. */ if (argc >= 5) DoFormat = (strcasecmp (argv[4], "Format") == 0); else DoFormat = 0; /* Open the raw device, and find out its geometry, so that we can figure out the cylinder size. */ if (DevicePath[0] != '/' || strlen (DevicePath) >= sizeof (PartitionInfo.device)) { printf ("Your device path should start with a / (slash) and\n"); printf ("not be longer than %d characters. It's currently\n", (int) (sizeof (PartitionInfo.device) - 1)); printf ("specified as \"%s\".\n", DevicePath); goto ErrorExit; } DeviceFile = open (DevicePath, O_RDWR); if (DeviceFile < 0) { printf ("Unable to open the raw device file \"%s\".\n", DevicePath); goto ErrorExit; } if (ioctl (DeviceFile, B_GET_GEOMETRY, &DeviceGeometry, sizeof (DeviceGeometry)) < 0) { printf ("Unable to get geometry of the raw device file \"%s\",\n" "maybe it isn't a device?\n", DevicePath); goto ErrorExit; } CylinderSize = DeviceGeometry.bytes_per_sector * (off_t) DeviceGeometry.sectors_per_track * DeviceGeometry.head_count; DeviceSize = CylinderSize * DeviceGeometry.cylinder_count; printf ("Cylinder size of \"%s\" is %qd bytes.\n", DevicePath, CylinderSize); printf ("Total device size is %d cylinders, or %qd bytes.\n", (int) DeviceGeometry.cylinder_count, DeviceSize); if (CylinderSize < 256) { printf ("That's too small a cylinder size to use, " "is the disk inserted?\n"); goto ErrorExit; } /* Round up the desired partition size to a multiple of cylinder size. */ PartitionSize = (PartitionSize + CylinderSize - 1) / CylinderSize * CylinderSize; if (PartitionSize < CylinderSize) PartitionSize = CylinderSize; /* Limit the number of partitions to the available space. Leave cylinder 0 unused so that other OSs can write their partition maps and other stuff there. */ if (CylinderSize + NumPartitions * PartitionSize > DeviceSize) NumPartitions = (DeviceSize - CylinderSize) / PartitionSize; if (NumPartitions < 1) { printf ("No partitions to make, maybe your size is too big?\n"); goto ErrorExit; } printf ("Making %d partitions of %qd bytes on device %s,\n" "%s formatting them%s. This will use up the first %qd bytes\n" "on the device (including skipped over cylinder #0).\n", NumPartitions, PartitionSize, DevicePath, DoFormat ? "will be" : "not", DoFormat ? " with BFS" : "", NumPartitions * PartitionSize + CylinderSize); /* Find the name of the directory to make the partitions in. Just take the device path name and cut off everything after the last / (slash) character. */ strcpy (PartitionDirectory, DevicePath); PartitionNamePntr = strrchr (PartitionDirectory, '/'); if (PartitionNamePntr == NULL) { printf ("Can't find last / in the device path name \"%s\".\n", DevicePath); goto ErrorExit; } PartitionNamePntr++; /* Point just after the last / character. */ /* OK, now make the partitions. */ for (PartitionIndex = 0; PartitionIndex < NumPartitions; PartitionIndex++) { /* Create the partition file. */ sprintf (PartitionNamePntr, "1_%d", PartitionIndex); printf ("\nCreating partition named \"%s\",\n", PartitionDirectory); PartitionFile = creat (PartitionDirectory, 0644 /* rwx permission flags, 0644 means owner R/W, others R. */); if (PartitionFile < 0) { printf ("Unable to create file \"%s\".\n", PartitionDirectory); goto ErrorExit; } /* Set up the partition info to make the file represent a portion of the raw device. */ memset (&PartitionInfo, 0, sizeof (&PartitionInfo)); PartitionInfo.logical_block_size = DeviceGeometry.bytes_per_sector; PartitionInfo.offset = CylinderSize + PartitionIndex * PartitionSize; PartitionInfo.size = PartitionSize; PartitionInfo.session = 1; /* We use session 1 to avoid standard #0. */ PartitionInfo.partition = PartitionIndex; strcpy (PartitionInfo.device, DevicePath); printf ("with starting offset %qd and size: %qd\n", PartitionInfo.offset, PartitionInfo.size); if (ioctl (PartitionFile, B_SET_PARTITION, &PartitionInfo, sizeof (PartitionInfo)) < 0) { printf ("B_SET_PARTITION failed to set the partition info!\n"); printf ("Perhaps you need to delete \"%s\" (and others) " "and try again?\n", PartitionDirectory); goto ErrorExit; } close (PartitionFile); PartitionFile = -1; /* Now try to format the new partition, if requested. */ if (DoFormat) { sprintf (CommandString, "mkbfs %s Disk%03d", PartitionDirectory, PartitionIndex); printf ("Executing command \"%s\".\n", CommandString); if (system (CommandString) < 0) { printf ("Failed to format the partition with command \"%s\".\n", CommandString); goto ErrorExit; } } /* Now mount the new partition, making a mount point directory first. */ sprintf (CommandString, "/Disk%03d", PartitionIndex); printf ("Making directory \"%s\".\n", CommandString); if (mkdir (CommandString, 0777) < 0) { printf ("Unable to make directory \"%s\".\n", CommandString); goto ErrorExit; } sprintf (CommandString, "mount %s /Disk%03d", PartitionDirectory, PartitionIndex); printf ("Executing command \"%s\".\n", CommandString); if (system (CommandString) < 0) { printf ("Failed to mount the partition with command \"%s\".\n", CommandString); goto ErrorExit; } } printf ("\n%s has finished, seemingly successfully.\n", argv[0]); ReturnCode = 0; ErrorExit: if (PartitionFile >= 0) close (PartitionFile); if (DeviceFile >= 0) close (DeviceFile); return ReturnCode; }