Line data Source code
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 : #include <sysexits.h>
4 : #include <sys/types.h>
5 : #include <sys/stat.h>
6 : #include <errno.h>
7 : #include <fcntl.h>
8 : #include <unistd.h>
9 : #include <ctype.h>
10 : #include <string.h>
11 : #include <libintl.h>
12 : #define _(String) gettext(String)
13 : #include <libgfs2.h>
14 : #include <uuid.h>
15 : #include "tunegfs2.h"
16 :
17 8 : int read_super(struct tunegfs2 *tfs)
18 : {
19 : void *block;
20 : int n;
21 8 : tfs->sb_start = GFS2_SB_ADDR << GFS2_BASIC_BLOCK_SHIFT;
22 8 : block = malloc(sizeof(char) * LGFS2_DEFAULT_BSIZE);
23 8 : if (!block) {
24 0 : perror("read_super: malloc");
25 0 : return EX_UNAVAILABLE;
26 : }
27 8 : n = pread(tfs->fd, block, LGFS2_DEFAULT_BSIZE, tfs->sb_start);
28 8 : if (n < 0) {
29 0 : perror("read_super: pread");
30 0 : free(block);
31 0 : return EX_IOERR;
32 : }
33 8 : tfs->sb = block;
34 8 : if (be32_to_cpu(tfs->sb->sb_header.mh_magic) != GFS2_MAGIC) {
35 2 : fprintf(stderr, _("Device does not contain a GFS or GFS2 file system\n"));
36 2 : tfs->sb = NULL;
37 2 : free(block);
38 2 : return EX_IOERR;
39 : }
40 : /* Ensure that table and proto are NULL terminated */
41 6 : tfs->sb->sb_lockproto[GFS2_LOCKNAME_LEN - 1] = '\0';
42 6 : tfs->sb->sb_locktable[GFS2_LOCKNAME_LEN - 1] = '\0';
43 6 : return 0;
44 : }
45 :
46 1 : static int is_gfs2(const struct tunegfs2 *tfs)
47 : {
48 1 : return be32_to_cpu(tfs->sb->sb_fs_format) == GFS2_FORMAT_FS;
49 : }
50 :
51 1 : int print_super(const struct tunegfs2 *tfs)
52 : {
53 : char readable_uuid[36+1];
54 :
55 1 : uuid_unparse(tfs->sb->sb_uuid, readable_uuid);
56 1 : printf(_("File system volume name: %s\n"), tfs->sb->sb_locktable);
57 1 : printf(_("File system UUID: %s\n"), readable_uuid);
58 1 : printf( _("File system magic number: 0x%X\n"), be32_to_cpu(tfs->sb->sb_header.mh_magic));
59 1 : printf(_("File system format version: %"PRIu32"\n"), be32_to_cpu(tfs->sb->sb_fs_format));
60 1 : printf(_("Block size: %d\n"), be32_to_cpu(tfs->sb->sb_bsize));
61 1 : printf(_("Block shift: %d\n"), be32_to_cpu(tfs->sb->sb_bsize_shift));
62 1 : printf(_("Root inode: %"PRIu64"\n"), be64_to_cpu(tfs->sb->sb_root_dir.no_addr));
63 1 : if (is_gfs2(tfs))
64 1 : printf(_("Master inode: %"PRIu64"\n"), be64_to_cpu(tfs->sb->sb_master_dir.no_addr));
65 1 : printf(_("Lock protocol: %s\n"), tfs->sb->sb_lockproto);
66 1 : printf(_("Lock table: %s\n"), tfs->sb->sb_locktable);
67 :
68 1 : return 0;
69 : }
70 :
71 2 : int write_super(const struct tunegfs2 *tfs)
72 : {
73 : int n;
74 2 : n = pwrite(tfs->fd, tfs->sb, LGFS2_DEFAULT_BSIZE, tfs->sb_start);
75 2 : if (n < 0) {
76 0 : perror("write_super: pwrite");
77 0 : return EX_IOERR;
78 : }
79 2 : return 0;
80 : }
81 :
82 1 : int change_uuid(struct tunegfs2 *tfs, const char *str)
83 : {
84 : uuid_t uuid;
85 : int status;
86 :
87 1 : status = uuid_parse(str, uuid);
88 1 : if (status == 0)
89 1 : uuid_copy(tfs->sb->sb_uuid, uuid);
90 1 : return status;
91 : }
92 :
93 0 : int change_lockproto(struct tunegfs2 *tfs, const char *lockproto)
94 : {
95 0 : int l = strlen(lockproto);
96 :
97 0 : if (l >= GFS2_LOCKNAME_LEN) {
98 0 : fprintf(stderr, _("Invalid lock protocol: %s\n"), _("too long"));
99 0 : return EX_DATAERR;
100 : }
101 :
102 0 : if (strncmp(lockproto, "lock_dlm", 8) &&
103 0 : strncmp(lockproto, "lock_nolock", 11)) {
104 0 : fprintf(stderr, _("Invalid lock protocol: %s\n"), lockproto);
105 0 : return EX_DATAERR;
106 : }
107 0 : memset(tfs->sb->sb_lockproto, '\0', GFS2_LOCKNAME_LEN);
108 0 : memcpy(tfs->sb->sb_lockproto, lockproto, l);
109 0 : return 0;
110 : }
111 :
112 0 : int change_locktable(struct tunegfs2 *tfs, const char *locktable)
113 : {
114 0 : const char *errpre = _("Invalid lock table:");
115 :
116 0 : if (strlen(locktable) >= GFS2_LOCKNAME_LEN) {
117 0 : fprintf(stderr, "%s %s\n", errpre, _("too long"));
118 0 : return EX_DATAERR;
119 : }
120 :
121 0 : if (strcmp(tfs->sb->sb_lockproto, "lock_dlm") == 0) {
122 0 : char *fsname = strchr(locktable, ':');
123 0 : if (fsname == NULL) {
124 0 : fprintf(stderr, "%s %s\n", errpre, _("missing colon"));
125 0 : return EX_DATAERR;
126 : }
127 0 : if (strlen(++fsname) > 30) {
128 0 : fprintf(stderr, "%s %s\n", errpre, _("file system name is too long"));
129 0 : return EX_DATAERR;
130 : }
131 0 : if (strchr(fsname, ':')) {
132 0 : fprintf(stderr, "%s %s\n", errpre, _("contains more than one colon"));
133 0 : return EX_DATAERR;
134 : }
135 : }
136 :
137 0 : strcpy(tfs->sb->sb_locktable, locktable);
138 0 : return 0;
139 : }
140 :
141 4 : int change_format(struct tunegfs2 *tfs, const char *format)
142 : {
143 : char *end;
144 : long ln;
145 :
146 4 : errno = 0;
147 4 : ln = strtol(format, &end, 10);
148 4 : if (errno || end == format || !LGFS2_FS_FORMAT_VALID(ln)) {
149 2 : fprintf(stderr, _("Invalid format option '%s'\n"), format);
150 2 : return EX_DATAERR;
151 : }
152 2 : if (ln < be32_to_cpu(tfs->sb->sb_fs_format)) {
153 1 : fprintf(stderr, _("Regressing the filesystem format is not supported\n"));
154 1 : return EX_DATAERR;
155 : }
156 1 : tfs->sb->sb_fs_format = cpu_to_be32(ln);
157 1 : return 0;
158 : }
|