Annotation of freem/src/fma_journals.c, revision 1.6
1.1 snw 1: /*
1.6 ! snw 2: * $Id: fma_journals.c,v 1.5 2025/04/13 04:22:43 snw Exp $
1.1 snw 3: * Journal utilities for fmadm
4: *
5: *
1.2 snw 6: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 7: * Copyright (C) 1998 MUG Deutschland
1.3 snw 8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
1.1 snw 9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
1.4 snw 26: * $Log: fma_journals.c,v $
1.6 ! snw 27: * Revision 1.5 2025/04/13 04:22:43 snw
! 28: * Fix snprintf calls
! 29: *
1.5 snw 30: * Revision 1.4 2025/04/09 19:52:02 snw
31: * Eliminate as many warnings as possible while building with -Wall
32: *
1.4 snw 33: * Revision 1.3 2025/03/09 19:14:25 snw
34: * First phase of REUSE compliance and header reformat
35: *
1.3 snw 36: *
37: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
38: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 39: **/
40:
41: #include <stdlib.h>
42: #include <stdio.h>
43: #include <stdlib.h>
44: #include <string.h>
45: #include <dirent.h>
46: #include <time.h>
47: #include <unistd.h>
48: #include <sys/types.h>
49: #include <sys/stat.h>
50: #include <fcntl.h>
51: #include <errno.h>
52:
53: #include "fmadm.h"
54: #include "jnldefs.h"
1.6 ! snw 55: #include "log.h"
1.1 snw 56:
57: void cvt_key (char *buf, char *key);
58: extern short ierr;
59:
60: int fma_journals_examine (int optc, char **opts)
61: {
62: register int i;
63: register int k;
64: int fd;
65: unsigned long siz;
66: unsigned long ct;
67:
68: char buf[2048];
69: char kbuf[1024];
70: char *tbuf;
71:
72: char dbuf[2049];
73:
74: jnl_hdr_t hdr;
75: jnl_ent_t ent;
76:
77: if ((fd = open (fma_journal_path, O_RDONLY)) == -1) {
1.6 ! snw 78: logprintf (FM_LOG_FATAL, "fmadm: error opening journal file %s (error code %ld [%s])",fma_journal_path, errno, strerror (errno));
1.1 snw 79: }
80:
81: if (read (fd, &hdr, sizeof (jnl_hdr_t)) == -1) {
1.6 ! snw 82: logprintf (FM_LOG_FATAL, "fmadm: error reading header from journal file %s (error code %ld [%s])", errno, fma_journal_path, strerror (errno));
1.1 snw 83: }
84:
85: printf ("\nFreeM Journal Dump\n");
86: printf ("------------------\n\n");
87:
88: printf ("Namespace: %s\n", fma_namespace);
89: printf ("Journal File: %s\n", fma_journal_path);
90: printf ("Journal Format Version: %d\n", hdr.fmt_version);
91: printf ("Cut Threshold: %s bytes\n", fma_journal_cut_threshold);
92:
93: lseek (fd, 0L, SEEK_SET);
94: siz = lseek (fd, 0L, SEEK_END);
95:
96: ct = (siz - sizeof (jnl_hdr_t)) / sizeof (jnl_ent_t);
97:
98: printf ("Journal Entries: %ld\n\n", ct);
99:
100: printf ("%-26s %-6s %-7s %-10s %s\n", "DATE", "PID", "TRNID", "ACTION", "DATA");
101: printf ("%-26s %-6s %-7s %-10s %s\n", "----", "---", "-----", "------", "----");
102:
103: lseek (fd, sizeof (jnl_hdr_t), SEEK_SET);
104:
105: for (i = 0; i < ct; i++) {
106:
107: read (fd, &ent, sizeof (jnl_ent_t));
108:
109: switch (ent.action) {
110:
111: case JNLA_TSTART:
112: strcpy (buf, "TSTART");
113: break;
114:
115: case JNLA_TROLLBACK:
116: strcpy (buf, "TROLLBACK");
117: break;
118:
119: case JNLA_TCOMMIT:
120: strcpy (buf, "TCOMMIT");
121: break;
122:
123: case JNLA_SET:
124: strcpy (buf, "SET");
125: break;
126:
127: case JNLA_KILL:
128: strcpy (buf, "KILL");
129: break;
130:
131: }
132:
133: cvt_key (kbuf, ent.key);
134:
135:
136: tbuf = ctime (&ent.ts);
137: tbuf[strlen(tbuf) - 1] = '\0';
138:
139: if (ent.action == JNLA_SET) {
140:
1.5 snw 141: snprintf (dbuf, sizeof (dbuf) - 1, "%s=%s", kbuf, ent.data);
1.1 snw 142:
143: for (k = 0; k < strlen (dbuf); k++) {
144: if (dbuf[k] == '\201') dbuf[k] = '\0';
145: }
146:
147: printf ("%-26s %-6d %-7ld %-10s %s\n", tbuf, ent.pid, ent.tran_id, buf, dbuf);
148:
149: }
150: else {
151: printf ("%-26s %-6d %-7ld %-10s %s\n", tbuf, ent.pid, ent.tran_id, buf, kbuf);
152: }
153:
154: }
155:
156: return 0;
157:
158: }
159:
160: int fma_journals_restore (int optc, char **opts)
161: {
162:
163: register int i;
164: int fd;
165: unsigned long siz;
166: unsigned long ct;
1.4 snw 167:
1.1 snw 168: jnl_hdr_t hdr;
169: jnl_ent_t ent;
1.6 ! snw 170:
1.1 snw 171: if ((fd = open (fma_journal_path, O_RDONLY)) == -1) {
1.6 ! snw 172: logprintf (FM_LOG_FATAL, "fmadm: error opening journal file %s (error code %ld [%s])",fma_journal_path, errno, strerror (errno));
1.1 snw 173: }
174:
175: if (read (fd, &hdr, sizeof (jnl_hdr_t)) == -1) {
1.6 ! snw 176: logprintf (FM_LOG_FATAL, "fmadm: error reading header from journal file %s (error code %ld [%s])", errno, fma_journal_path, strerror (errno));
1.1 snw 177: }
178:
179: printf ("\nFreeM Journal Playback\n");
180: printf ("----------------------\n\n");
181:
182: printf ("Namespace: %s\n", fma_namespace);
183: printf ("Journal File: %s\n", fma_journal_path);
184: printf ("Journal Format Version: %d\n", hdr.fmt_version);
185: printf ("Cut Threshold: %s bytes\n", fma_journal_cut_threshold);
186:
187: lseek (fd, 0L, SEEK_SET);
188: siz = lseek (fd, 0L, SEEK_END);
189:
190: ct = (siz - sizeof (jnl_hdr_t)) / sizeof (jnl_ent_t);
191:
192: printf ("Journal Entries: %ld\n\n", ct);
193:
194:
195: lseek (fd, sizeof (jnl_hdr_t), SEEK_SET);
196:
197: for (i = 0; i < ct; i++) {
198:
199: read (fd, &ent, sizeof (jnl_ent_t));
200:
201: switch (ent.action) {
202:
203: case JNLA_TSTART:
204: printf (" Played back TSTART (transaction id %ld)\n", ent.tran_id);
205: break;
206:
207: case JNLA_TROLLBACK:
208: printf (" Played back TROLLBACK (transaction id %ld)\n", ent.tran_id);
209: break;
210:
211: case JNLA_TCOMMIT:
212: printf (" Played back TCOMMIT (transaction id %ld)\n", ent.tran_id);
213: break;
214:
215: case JNLA_SET:
216: global (set_sym, ent.key, ent.data);
217: printf (" Played back SET (transaction id %ld)\n", ent.tran_id);
218: break;
219:
220: case JNLA_KILL:
221: global (kill_sym, ent.key, ent.data);
222: printf (" Played back KILL (transaction id %ld)\n", ent.tran_id);
223: break;
224:
225: }
226:
227: }
228:
229: return 0;
230:
231: }
232:
233:
234: void cvt_key (char *buf, char *key)
235: {
236: int i;
237: int j = 0;
238: int first = 1;
239:
240: if (key[0] == '\0') {
241: buf[0] = '\0';
242:
243: return;
244: }
245:
246: for(i = 0; i < 1023; i++) {
247:
248: switch (key[i]) {
249:
250: case '\201':
251: if (first == 0) {
252: buf[j] = ')';
253: buf[j + 1] = '\0';
254: }
255: else {
256: buf[j] = '\0';
257: }
258: return;
259:
260: case '\202':
261: if (first == 1) {
262: buf[j] = '(';
263: first = 0;
264: }
265: else {
266: buf[j] = ',';
267: }
268:
269: break;
270:
271: default:
272: buf[j] = key[i];
273: break;
274: }
275:
276: j++;
277: }
278:
279: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>