Annotation of freem/src/fma_journals.c, revision 1.4
1.1 snw 1: /*
1.4 ! snw 2: * $Id: fma_journals.c,v 1.3 2025/03/09 19:14:25 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 $
! 27: * Revision 1.3 2025/03/09 19:14:25 snw
! 28: * First phase of REUSE compliance and header reformat
! 29: *
1.3 snw 30: *
31: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
32: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 33: **/
34:
35: #include <stdlib.h>
36: #include <stdio.h>
37: #include <stdlib.h>
38: #include <string.h>
39: #include <dirent.h>
40: #include <time.h>
41: #include <unistd.h>
42: #include <sys/types.h>
43: #include <sys/stat.h>
44: #include <fcntl.h>
45: #include <errno.h>
46:
47: #include "fmadm.h"
48: #include "jnldefs.h"
49:
50: void cvt_key (char *buf, char *key);
51: extern short ierr;
52:
53: int fma_journals_examine (int optc, char **opts)
54: {
55: register int i;
56: register int k;
57: int fd;
58: unsigned long siz;
59: unsigned long ct;
60:
61: char buf[2048];
62: char kbuf[1024];
63: char *tbuf;
64:
65: char dbuf[2049];
66:
67: jnl_hdr_t hdr;
68: jnl_ent_t ent;
69:
70: if ((fd = open (fma_journal_path, O_RDONLY)) == -1) {
71: fprintf (stderr, "fmadm: error %d opening journal file %s (%s)\n", errno, fma_journal_path, strerror (errno));
72:
73: exit (2);
74: }
75:
76: if (read (fd, &hdr, sizeof (jnl_hdr_t)) == -1) {
77: fprintf (stderr, "fmadm: error %d reading header from journal file %s (%s)\n", errno, fma_journal_path, strerror (errno));
78:
79: exit (3);
80: }
81:
82: printf ("\nFreeM Journal Dump\n");
83: printf ("------------------\n\n");
84:
85: printf ("Namespace: %s\n", fma_namespace);
86: printf ("Journal File: %s\n", fma_journal_path);
87: printf ("Journal Format Version: %d\n", hdr.fmt_version);
88: printf ("Cut Threshold: %s bytes\n", fma_journal_cut_threshold);
89:
90: lseek (fd, 0L, SEEK_SET);
91: siz = lseek (fd, 0L, SEEK_END);
92:
93: ct = (siz - sizeof (jnl_hdr_t)) / sizeof (jnl_ent_t);
94:
95: printf ("Journal Entries: %ld\n\n", ct);
96:
97: printf ("%-26s %-6s %-7s %-10s %s\n", "DATE", "PID", "TRNID", "ACTION", "DATA");
98: printf ("%-26s %-6s %-7s %-10s %s\n", "----", "---", "-----", "------", "----");
99:
100: lseek (fd, sizeof (jnl_hdr_t), SEEK_SET);
101:
102: for (i = 0; i < ct; i++) {
103:
104: read (fd, &ent, sizeof (jnl_ent_t));
105:
106: switch (ent.action) {
107:
108: case JNLA_TSTART:
109: strcpy (buf, "TSTART");
110: break;
111:
112: case JNLA_TROLLBACK:
113: strcpy (buf, "TROLLBACK");
114: break;
115:
116: case JNLA_TCOMMIT:
117: strcpy (buf, "TCOMMIT");
118: break;
119:
120: case JNLA_SET:
121: strcpy (buf, "SET");
122: break;
123:
124: case JNLA_KILL:
125: strcpy (buf, "KILL");
126: break;
127:
128: }
129:
130: cvt_key (kbuf, ent.key);
131:
132:
133: tbuf = ctime (&ent.ts);
134: tbuf[strlen(tbuf) - 1] = '\0';
135:
136: if (ent.action == JNLA_SET) {
137:
138: snprintf (dbuf, 2049, "%s=%s", kbuf, ent.data);
139:
140: for (k = 0; k < strlen (dbuf); k++) {
141: if (dbuf[k] == '\201') dbuf[k] = '\0';
142: }
143:
144: printf ("%-26s %-6d %-7ld %-10s %s\n", tbuf, ent.pid, ent.tran_id, buf, dbuf);
145:
146: }
147: else {
148: printf ("%-26s %-6d %-7ld %-10s %s\n", tbuf, ent.pid, ent.tran_id, buf, kbuf);
149: }
150:
151: }
152:
153: return 0;
154:
155: }
156:
157: int fma_journals_restore (int optc, char **opts)
158: {
159:
160: register int i;
161: int fd;
162: unsigned long siz;
163: unsigned long ct;
1.4 ! snw 164:
1.1 snw 165: jnl_hdr_t hdr;
166: jnl_ent_t ent;
167:
168: if ((fd = open (fma_journal_path, O_RDONLY)) == -1) {
169: fprintf (stderr, "error: error %d opening journal file %s\n", errno, fma_journal_path);
170:
171: exit (2);
172: }
173:
174: if (read (fd, &hdr, sizeof (jnl_hdr_t)) == -1) {
175: fprintf (stderr, "error: error %d reading header from journal file %s\n", errno, fma_journal_path);
176:
177: exit (3);
178: }
179:
180: printf ("\nFreeM Journal Playback\n");
181: printf ("----------------------\n\n");
182:
183: printf ("Namespace: %s\n", fma_namespace);
184: printf ("Journal File: %s\n", fma_journal_path);
185: printf ("Journal Format Version: %d\n", hdr.fmt_version);
186: printf ("Cut Threshold: %s bytes\n", fma_journal_cut_threshold);
187:
188: lseek (fd, 0L, SEEK_SET);
189: siz = lseek (fd, 0L, SEEK_END);
190:
191: ct = (siz - sizeof (jnl_hdr_t)) / sizeof (jnl_ent_t);
192:
193: printf ("Journal Entries: %ld\n\n", ct);
194:
195:
196: lseek (fd, sizeof (jnl_hdr_t), SEEK_SET);
197:
198: for (i = 0; i < ct; i++) {
199:
200: read (fd, &ent, sizeof (jnl_ent_t));
201:
202: switch (ent.action) {
203:
204: case JNLA_TSTART:
205: printf (" Played back TSTART (transaction id %ld)\n", ent.tran_id);
206: break;
207:
208: case JNLA_TROLLBACK:
209: printf (" Played back TROLLBACK (transaction id %ld)\n", ent.tran_id);
210: break;
211:
212: case JNLA_TCOMMIT:
213: printf (" Played back TCOMMIT (transaction id %ld)\n", ent.tran_id);
214: break;
215:
216: case JNLA_SET:
217: global (set_sym, ent.key, ent.data);
218: printf (" Played back SET (transaction id %ld)\n", ent.tran_id);
219: break;
220:
221: case JNLA_KILL:
222: global (kill_sym, ent.key, ent.data);
223: printf (" Played back KILL (transaction id %ld)\n", ent.tran_id);
224: break;
225:
226: }
227:
228: }
229:
230: return 0;
231:
232: }
233:
234:
235: void cvt_key (char *buf, char *key)
236: {
237: int i;
238: int j = 0;
239: int first = 1;
240:
241: if (key[0] == '\0') {
242: buf[0] = '\0';
243:
244: return;
245: }
246:
247: for(i = 0; i < 1023; i++) {
248:
249: switch (key[i]) {
250:
251: case '\201':
252: if (first == 0) {
253: buf[j] = ')';
254: buf[j + 1] = '\0';
255: }
256: else {
257: buf[j] = '\0';
258: }
259: return;
260:
261: case '\202':
262: if (first == 1) {
263: buf[j] = '(';
264: first = 0;
265: }
266: else {
267: buf[j] = ',';
268: }
269:
270: break;
271:
272: default:
273: buf[j] = key[i];
274: break;
275: }
276:
277: j++;
278: }
279:
280: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>