blob: 482a3062dbb3babf2d20a9d8f32e2a71aa819acd [file] [log] [blame]
bigbiff7b4c7a62015-01-01 19:44:14 -05001
2#include "fdiskP.h"
3#include "pathnames.h"
4
5#include <ctype.h>
6
7/**
8 * SECTION: utils
9 * @title: Utils
10 * @short_description: misc fdisk functions
11 */
12
13/*
14 * Zeros in-memory first sector buffer
15 */
16int fdisk_init_firstsector_buffer(struct fdisk_context *cxt)
17{
18 if (!cxt)
19 return -EINVAL;
20
21 if (!cxt->firstsector || cxt->firstsector_bufsz != cxt->sector_size) {
22 /* Let's allocate a new buffer if no allocated yet, or the
23 * current buffer has incorrect size */
24 if (!cxt->parent || cxt->parent->firstsector != cxt->firstsector)
25 free(cxt->firstsector);
26
27 DBG(CXT, ul_debugobj(cxt, "initialize in-memory first sector "
28 "buffer [sector_size=%lu]", cxt->sector_size));
29 cxt->firstsector = calloc(1, cxt->sector_size);
30 if (!cxt->firstsector)
31 return -ENOMEM;
32
33 cxt->firstsector_bufsz = cxt->sector_size;
34 return 0;
35 }
36
37 DBG(CXT, ul_debugobj(cxt, "zeroize in-memory first sector buffer"));
38 memset(cxt->firstsector, 0, cxt->firstsector_bufsz);
39 return 0;
40}
41
42int fdisk_read_firstsector(struct fdisk_context *cxt)
43{
44 ssize_t r;
45 int rc;
46
47 assert(cxt);
48 assert(cxt->sector_size);
49
50 rc = fdisk_init_firstsector_buffer(cxt);
51 if (rc)
52 return rc;
53
54 assert(cxt->sector_size == cxt->firstsector_bufsz);
55
56 DBG(CXT, ul_debugobj(cxt, "reading first sector "
57 "buffer [sector_size=%lu]", cxt->sector_size));
58
59 r = lseek(cxt->dev_fd, 0, SEEK_SET);
60 if (r == -1)
61 {
62 DBG(CXT, ul_debugobj(cxt, "failed to seek to first sector %m"));
63 return -errno;
64 }
65
66 r = read(cxt->dev_fd, cxt->firstsector, cxt->sector_size);
67
68 if (r != cxt->sector_size) {
69 if (!errno)
70 errno = EINVAL; /* probably too small file/device */
71 DBG(CXT, ul_debugobj(cxt, "failed to read first sector %m"));
72 return -errno;
73 }
74
75 return 0;
76}
77
78/**
79 * fdisk_partname:
80 * @dev: device name
81 * @partno: partition name
82 *
83 * Return: allocated buffer with partition name, use free() to deallocate.
84 */
85char *fdisk_partname(const char *dev, size_t partno)
86{
87 char *res = NULL;
88 const char *p = "";
89 int w = 0;
90
91 if (!dev || !*dev) {
92 if (asprintf(&res, "%zd", partno) > 0)
93 return res;
94 return NULL;
95 }
96
97 w = strlen(dev);
98 if (isdigit(dev[w - 1]))
99#ifdef __GNU__
100 p = "s";
101#else
102 p = "p";
103#endif
104
105 /* devfs kludge - note: fdisk partition names are not supposed
106 to equal kernel names, so there is no reason to do this */
107 if (strcmp(dev + w - 4, "disc") == 0) {
108 w -= 4;
109 p = "part";
110 }
111
112 /* udev names partitions by appending -partN
113 e.g. ata-SAMSUNG_SV8004H_0357J1FT712448-part1 */
114 if ((strncmp(dev, _PATH_DEV_BYID, sizeof(_PATH_DEV_BYID) - 1) == 0) ||
115 strncmp(dev, _PATH_DEV_BYPATH, sizeof(_PATH_DEV_BYPATH) - 1) == 0) {
116 p = "-part";
117 }
118
119 if (asprintf(&res, "%.*s%s%zu", w, dev, p, partno) > 0)
120 return res;
121
122 return NULL;
123}
124
125#ifdef TEST_PROGRAM
126struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt) { return NULL; }
127struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt) { return NULL; }
128
129int test_partnames(struct fdisk_test *ts, int argc, char *argv[])
130{
131 size_t i;
132 const char *disk = argv[1];
133
134 for (i = 0; i < 5; i++) {
135 char *p = fdisk_partname(disk, i + 1);
136 if (p)
137 printf("%zu: '%s'\n", i + 1, p);
138 free(p);
139 }
140
141 return 0;
142}
143
144int main(int argc, char *argv[])
145{
146 struct fdisk_test tss[] = {
147 { "--partnames", test_partnames, "<diskname>" },
148 { NULL }
149 };
150
151 return fdisk_run_test(tss, argc, argv);
152}
153
154#endif