1b8ba871bSPeter Wemm /*- 2b8ba871bSPeter Wemm * Copyright (c) 1992, 1993, 1994 3b8ba871bSPeter Wemm * The Regents of the University of California. All rights reserved. 4b8ba871bSPeter Wemm * Copyright (c) 1992, 1993, 1994, 1995, 1996 5b8ba871bSPeter Wemm * Keith Bostic. All rights reserved. 6b8ba871bSPeter Wemm * 7b8ba871bSPeter Wemm * See the LICENSE file for redistribution information. 8b8ba871bSPeter Wemm */ 9b8ba871bSPeter Wemm 10b8ba871bSPeter Wemm #include "config.h" 11b8ba871bSPeter Wemm 12b8ba871bSPeter Wemm #ifndef lint 13f0957ccaSPeter Wemm static const char sccsid[] = "$Id: log.c,v 10.27 2011/07/13 06:25:50 zy Exp $"; 14b8ba871bSPeter Wemm #endif /* not lint */ 15b8ba871bSPeter Wemm 16b8ba871bSPeter Wemm #include <sys/types.h> 17b8ba871bSPeter Wemm #include <sys/queue.h> 18b8ba871bSPeter Wemm #include <sys/stat.h> 19b8ba871bSPeter Wemm 20b8ba871bSPeter Wemm #include <bitstring.h> 21b8ba871bSPeter Wemm #include <errno.h> 22b8ba871bSPeter Wemm #include <fcntl.h> 23b8ba871bSPeter Wemm #include <limits.h> 24f0957ccaSPeter Wemm #include <stdint.h> 25b8ba871bSPeter Wemm #include <stdio.h> 26b8ba871bSPeter Wemm #include <stdlib.h> 27b8ba871bSPeter Wemm #include <string.h> 28b8ba871bSPeter Wemm 29b8ba871bSPeter Wemm #include "common.h" 30b8ba871bSPeter Wemm 31b8ba871bSPeter Wemm /* 32b8ba871bSPeter Wemm * The log consists of records, each containing a type byte and a variable 33b8ba871bSPeter Wemm * length byte string, as follows: 34b8ba871bSPeter Wemm * 35b8ba871bSPeter Wemm * LOG_CURSOR_INIT MARK 36b8ba871bSPeter Wemm * LOG_CURSOR_END MARK 37b8ba871bSPeter Wemm * LOG_LINE_APPEND recno_t char * 38b8ba871bSPeter Wemm * LOG_LINE_DELETE recno_t char * 39b8ba871bSPeter Wemm * LOG_LINE_INSERT recno_t char * 40b8ba871bSPeter Wemm * LOG_LINE_RESET_F recno_t char * 41b8ba871bSPeter Wemm * LOG_LINE_RESET_B recno_t char * 42b8ba871bSPeter Wemm * LOG_MARK LMARK 43b8ba871bSPeter Wemm * 44b8ba871bSPeter Wemm * We do before image physical logging. This means that the editor layer 45b8ba871bSPeter Wemm * MAY NOT modify records in place, even if simply deleting or overwriting 46b8ba871bSPeter Wemm * characters. Since the smallest unit of logging is a line, we're using 47b8ba871bSPeter Wemm * up lots of space. This may eventually have to be reduced, probably by 48b8ba871bSPeter Wemm * doing logical logging, which is a much cooler database phrase. 49b8ba871bSPeter Wemm * 50b8ba871bSPeter Wemm * The implementation of the historic vi 'u' command, using roll-forward and 51b8ba871bSPeter Wemm * roll-back, is simple. Each set of changes has a LOG_CURSOR_INIT record, 52b8ba871bSPeter Wemm * followed by a number of other records, followed by a LOG_CURSOR_END record. 53b8ba871bSPeter Wemm * LOG_LINE_RESET records come in pairs. The first is a LOG_LINE_RESET_B 54b8ba871bSPeter Wemm * record, and is the line before the change. The second is LOG_LINE_RESET_F, 55b8ba871bSPeter Wemm * and is the line after the change. Roll-back is done by backing up to the 56b8ba871bSPeter Wemm * first LOG_CURSOR_INIT record before a change. Roll-forward is done in a 57b8ba871bSPeter Wemm * similar fashion. 58b8ba871bSPeter Wemm * 59b8ba871bSPeter Wemm * The 'U' command is implemented by rolling backward to a LOG_CURSOR_END 60b8ba871bSPeter Wemm * record for a line different from the current one. It should be noted that 61b8ba871bSPeter Wemm * this means that a subsequent 'u' command will make a change based on the 62b8ba871bSPeter Wemm * new position of the log's cursor. This is okay, and, in fact, historic vi 63b8ba871bSPeter Wemm * behaved that way. 64b8ba871bSPeter Wemm */ 65b8ba871bSPeter Wemm 66*c271fa92SBaptiste Daroussin static int log_cursor1(SCR *, int); 67*c271fa92SBaptiste Daroussin static void log_err(SCR *, char *, int); 68b8ba871bSPeter Wemm #if defined(DEBUG) && 0 69*c271fa92SBaptiste Daroussin static void log_trace(SCR *, char *, recno_t, u_char *); 70b8ba871bSPeter Wemm #endif 71*c271fa92SBaptiste Daroussin static int apply_with(int (*)(SCR *, recno_t, CHAR_T *, size_t), 72*c271fa92SBaptiste Daroussin SCR *, recno_t, u_char *, size_t); 73b8ba871bSPeter Wemm 74b8ba871bSPeter Wemm /* Try and restart the log on failure, i.e. if we run out of memory. */ 75b8ba871bSPeter Wemm #define LOG_ERR { \ 76b8ba871bSPeter Wemm log_err(sp, __FILE__, __LINE__); \ 77b8ba871bSPeter Wemm return (1); \ 78b8ba871bSPeter Wemm } 79b8ba871bSPeter Wemm 80f0957ccaSPeter Wemm /* offset of CHAR_T string in log needs to be aligned on some systems 81f0957ccaSPeter Wemm * because it is passed to db_set as a string 82f0957ccaSPeter Wemm */ 83f0957ccaSPeter Wemm typedef struct { 84f0957ccaSPeter Wemm char data[sizeof(u_char) /* type */ + sizeof(recno_t)]; 85f0957ccaSPeter Wemm CHAR_T str[1]; 86f0957ccaSPeter Wemm } log_t; 87f0957ccaSPeter Wemm #define CHAR_T_OFFSET ((char *)(((log_t*)0)->str) - (char *)0) 88f0957ccaSPeter Wemm 89b8ba871bSPeter Wemm /* 90b8ba871bSPeter Wemm * log_init -- 91b8ba871bSPeter Wemm * Initialize the logging subsystem. 92b8ba871bSPeter Wemm * 93*c271fa92SBaptiste Daroussin * PUBLIC: int log_init(SCR *, EXF *); 94b8ba871bSPeter Wemm */ 95b8ba871bSPeter Wemm int 96f0957ccaSPeter Wemm log_init( 97f0957ccaSPeter Wemm SCR *sp, 98f0957ccaSPeter Wemm EXF *ep) 99b8ba871bSPeter Wemm { 100b8ba871bSPeter Wemm /* 101b8ba871bSPeter Wemm * !!! 102b8ba871bSPeter Wemm * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER. 103b8ba871bSPeter Wemm * 104b8ba871bSPeter Wemm * Initialize the buffer. The logging subsystem has its own 105b8ba871bSPeter Wemm * buffers because the global ones are almost by definition 106b8ba871bSPeter Wemm * going to be in use when the log runs. 107b8ba871bSPeter Wemm */ 108b8ba871bSPeter Wemm ep->l_lp = NULL; 109b8ba871bSPeter Wemm ep->l_len = 0; 110b8ba871bSPeter Wemm ep->l_cursor.lno = 1; /* XXX Any valid recno. */ 111b8ba871bSPeter Wemm ep->l_cursor.cno = 0; 112b8ba871bSPeter Wemm ep->l_high = ep->l_cur = 1; 113b8ba871bSPeter Wemm 114b8ba871bSPeter Wemm ep->log = dbopen(NULL, O_CREAT | O_NONBLOCK | O_RDWR, 115b8ba871bSPeter Wemm S_IRUSR | S_IWUSR, DB_RECNO, NULL); 116b8ba871bSPeter Wemm if (ep->log == NULL) { 117b8ba871bSPeter Wemm msgq(sp, M_SYSERR, "009|Log file"); 118b8ba871bSPeter Wemm F_SET(ep, F_NOLOG); 119b8ba871bSPeter Wemm return (1); 120b8ba871bSPeter Wemm } 121b8ba871bSPeter Wemm 122b8ba871bSPeter Wemm return (0); 123b8ba871bSPeter Wemm } 124b8ba871bSPeter Wemm 125b8ba871bSPeter Wemm /* 126b8ba871bSPeter Wemm * log_end -- 127b8ba871bSPeter Wemm * Close the logging subsystem. 128b8ba871bSPeter Wemm * 129*c271fa92SBaptiste Daroussin * PUBLIC: int log_end(SCR *, EXF *); 130b8ba871bSPeter Wemm */ 131b8ba871bSPeter Wemm int 132f0957ccaSPeter Wemm log_end( 133f0957ccaSPeter Wemm SCR *sp, 134f0957ccaSPeter Wemm EXF *ep) 135b8ba871bSPeter Wemm { 136b8ba871bSPeter Wemm /* 137b8ba871bSPeter Wemm * !!! 138b8ba871bSPeter Wemm * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER. 139b8ba871bSPeter Wemm */ 140b8ba871bSPeter Wemm if (ep->log != NULL) { 141b8ba871bSPeter Wemm (void)(ep->log->close)(ep->log); 142b8ba871bSPeter Wemm ep->log = NULL; 143b8ba871bSPeter Wemm } 144b8ba871bSPeter Wemm if (ep->l_lp != NULL) { 145b8ba871bSPeter Wemm free(ep->l_lp); 146b8ba871bSPeter Wemm ep->l_lp = NULL; 147b8ba871bSPeter Wemm } 148b8ba871bSPeter Wemm ep->l_len = 0; 149b8ba871bSPeter Wemm ep->l_cursor.lno = 1; /* XXX Any valid recno. */ 150b8ba871bSPeter Wemm ep->l_cursor.cno = 0; 151b8ba871bSPeter Wemm ep->l_high = ep->l_cur = 1; 152b8ba871bSPeter Wemm return (0); 153b8ba871bSPeter Wemm } 154b8ba871bSPeter Wemm 155b8ba871bSPeter Wemm /* 156b8ba871bSPeter Wemm * log_cursor -- 157b8ba871bSPeter Wemm * Log the current cursor position, starting an event. 158b8ba871bSPeter Wemm * 159*c271fa92SBaptiste Daroussin * PUBLIC: int log_cursor(SCR *); 160b8ba871bSPeter Wemm */ 161b8ba871bSPeter Wemm int 162f0957ccaSPeter Wemm log_cursor(SCR *sp) 163b8ba871bSPeter Wemm { 164b8ba871bSPeter Wemm EXF *ep; 165b8ba871bSPeter Wemm 166b8ba871bSPeter Wemm ep = sp->ep; 167b8ba871bSPeter Wemm if (F_ISSET(ep, F_NOLOG)) 168b8ba871bSPeter Wemm return (0); 169b8ba871bSPeter Wemm 170b8ba871bSPeter Wemm /* 171b8ba871bSPeter Wemm * If any changes were made since the last cursor init, 172b8ba871bSPeter Wemm * put out the ending cursor record. 173b8ba871bSPeter Wemm */ 174b8ba871bSPeter Wemm if (ep->l_cursor.lno == OOBLNO) { 175b8ba871bSPeter Wemm ep->l_cursor.lno = sp->lno; 176b8ba871bSPeter Wemm ep->l_cursor.cno = sp->cno; 177b8ba871bSPeter Wemm return (log_cursor1(sp, LOG_CURSOR_END)); 178b8ba871bSPeter Wemm } 179b8ba871bSPeter Wemm ep->l_cursor.lno = sp->lno; 180b8ba871bSPeter Wemm ep->l_cursor.cno = sp->cno; 181b8ba871bSPeter Wemm return (0); 182b8ba871bSPeter Wemm } 183b8ba871bSPeter Wemm 184b8ba871bSPeter Wemm /* 185b8ba871bSPeter Wemm * log_cursor1 -- 186b8ba871bSPeter Wemm * Actually push a cursor record out. 187b8ba871bSPeter Wemm */ 188b8ba871bSPeter Wemm static int 189f0957ccaSPeter Wemm log_cursor1( 190f0957ccaSPeter Wemm SCR *sp, 191f0957ccaSPeter Wemm int type) 192b8ba871bSPeter Wemm { 193b8ba871bSPeter Wemm DBT data, key; 194b8ba871bSPeter Wemm EXF *ep; 195b8ba871bSPeter Wemm 196b8ba871bSPeter Wemm ep = sp->ep; 197f0957ccaSPeter Wemm 198f0957ccaSPeter Wemm BINC_RETC(sp, ep->l_lp, ep->l_len, sizeof(u_char) + sizeof(MARK)); 199b8ba871bSPeter Wemm ep->l_lp[0] = type; 200b8ba871bSPeter Wemm memmove(ep->l_lp + sizeof(u_char), &ep->l_cursor, sizeof(MARK)); 201b8ba871bSPeter Wemm 202b8ba871bSPeter Wemm key.data = &ep->l_cur; 203b8ba871bSPeter Wemm key.size = sizeof(recno_t); 204b8ba871bSPeter Wemm data.data = ep->l_lp; 205b8ba871bSPeter Wemm data.size = sizeof(u_char) + sizeof(MARK); 206b8ba871bSPeter Wemm if (ep->log->put(ep->log, &key, &data, 0) == -1) 207b8ba871bSPeter Wemm LOG_ERR; 208b8ba871bSPeter Wemm 209b8ba871bSPeter Wemm #if defined(DEBUG) && 0 210b8ba871bSPeter Wemm TRACE(sp, "%lu: %s: %u/%u\n", ep->l_cur, 211b8ba871bSPeter Wemm type == LOG_CURSOR_INIT ? "log_cursor_init" : "log_cursor_end", 212b8ba871bSPeter Wemm sp->lno, sp->cno); 213b8ba871bSPeter Wemm #endif 214b8ba871bSPeter Wemm /* Reset high water mark. */ 215b8ba871bSPeter Wemm ep->l_high = ++ep->l_cur; 216b8ba871bSPeter Wemm 217b8ba871bSPeter Wemm return (0); 218b8ba871bSPeter Wemm } 219b8ba871bSPeter Wemm 220b8ba871bSPeter Wemm /* 221b8ba871bSPeter Wemm * log_line -- 222b8ba871bSPeter Wemm * Log a line change. 223b8ba871bSPeter Wemm * 224*c271fa92SBaptiste Daroussin * PUBLIC: int log_line(SCR *, recno_t, u_int); 225b8ba871bSPeter Wemm */ 226b8ba871bSPeter Wemm int 227f0957ccaSPeter Wemm log_line( 228f0957ccaSPeter Wemm SCR *sp, 229f0957ccaSPeter Wemm recno_t lno, 230f0957ccaSPeter Wemm u_int action) 231b8ba871bSPeter Wemm { 232b8ba871bSPeter Wemm DBT data, key; 233b8ba871bSPeter Wemm EXF *ep; 234b8ba871bSPeter Wemm size_t len; 235f0957ccaSPeter Wemm CHAR_T *lp; 236f0957ccaSPeter Wemm recno_t lcur; 237b8ba871bSPeter Wemm 238b8ba871bSPeter Wemm ep = sp->ep; 239b8ba871bSPeter Wemm if (F_ISSET(ep, F_NOLOG)) 240b8ba871bSPeter Wemm return (0); 241b8ba871bSPeter Wemm 242b8ba871bSPeter Wemm /* 243b8ba871bSPeter Wemm * XXX 244b8ba871bSPeter Wemm * 245b8ba871bSPeter Wemm * Kluge for vi. Clear the EXF undo flag so that the 246b8ba871bSPeter Wemm * next 'u' command does a roll-back, regardless. 247b8ba871bSPeter Wemm */ 248b8ba871bSPeter Wemm F_CLR(ep, F_UNDO); 249b8ba871bSPeter Wemm 250b8ba871bSPeter Wemm /* Put out one initial cursor record per set of changes. */ 251b8ba871bSPeter Wemm if (ep->l_cursor.lno != OOBLNO) { 252b8ba871bSPeter Wemm if (log_cursor1(sp, LOG_CURSOR_INIT)) 253b8ba871bSPeter Wemm return (1); 254b8ba871bSPeter Wemm ep->l_cursor.lno = OOBLNO; 255b8ba871bSPeter Wemm } 256b8ba871bSPeter Wemm 257b8ba871bSPeter Wemm /* 258b8ba871bSPeter Wemm * Put out the changes. If it's a LOG_LINE_RESET_B call, it's a 259b8ba871bSPeter Wemm * special case, avoid the caches. Also, if it fails and it's 260b8ba871bSPeter Wemm * line 1, it just means that the user started with an empty file, 261b8ba871bSPeter Wemm * so fake an empty length line. 262b8ba871bSPeter Wemm */ 263b8ba871bSPeter Wemm if (action == LOG_LINE_RESET_B) { 264b8ba871bSPeter Wemm if (db_get(sp, lno, DBG_NOCACHE, &lp, &len)) { 265b8ba871bSPeter Wemm if (lno != 1) { 266b8ba871bSPeter Wemm db_err(sp, lno); 267b8ba871bSPeter Wemm return (1); 268b8ba871bSPeter Wemm } 269b8ba871bSPeter Wemm len = 0; 270f0957ccaSPeter Wemm lp = L(""); 271b8ba871bSPeter Wemm } 272b8ba871bSPeter Wemm } else 273b8ba871bSPeter Wemm if (db_get(sp, lno, DBG_FATAL, &lp, &len)) 274b8ba871bSPeter Wemm return (1); 275f0957ccaSPeter Wemm BINC_RETC(sp, 276f0957ccaSPeter Wemm ep->l_lp, ep->l_len, 277f0957ccaSPeter Wemm len * sizeof(CHAR_T) + CHAR_T_OFFSET); 278b8ba871bSPeter Wemm ep->l_lp[0] = action; 279b8ba871bSPeter Wemm memmove(ep->l_lp + sizeof(u_char), &lno, sizeof(recno_t)); 280f0957ccaSPeter Wemm memmove(ep->l_lp + CHAR_T_OFFSET, lp, len * sizeof(CHAR_T)); 281b8ba871bSPeter Wemm 282f0957ccaSPeter Wemm lcur = ep->l_cur; 283f0957ccaSPeter Wemm key.data = &lcur; 284b8ba871bSPeter Wemm key.size = sizeof(recno_t); 285b8ba871bSPeter Wemm data.data = ep->l_lp; 286f0957ccaSPeter Wemm data.size = len * sizeof(CHAR_T) + CHAR_T_OFFSET; 287b8ba871bSPeter Wemm if (ep->log->put(ep->log, &key, &data, 0) == -1) 288b8ba871bSPeter Wemm LOG_ERR; 289b8ba871bSPeter Wemm 290b8ba871bSPeter Wemm #if defined(DEBUG) && 0 291b8ba871bSPeter Wemm switch (action) { 292b8ba871bSPeter Wemm case LOG_LINE_APPEND: 293f0957ccaSPeter Wemm TRACE(sp, "%lu: log_line: append: %lu {%u}\n", 294b8ba871bSPeter Wemm ep->l_cur, lno, len); 295b8ba871bSPeter Wemm break; 296b8ba871bSPeter Wemm case LOG_LINE_DELETE: 297b8ba871bSPeter Wemm TRACE(sp, "%lu: log_line: delete: %lu {%u}\n", 298b8ba871bSPeter Wemm ep->l_cur, lno, len); 299b8ba871bSPeter Wemm break; 300b8ba871bSPeter Wemm case LOG_LINE_INSERT: 301b8ba871bSPeter Wemm TRACE(sp, "%lu: log_line: insert: %lu {%u}\n", 302b8ba871bSPeter Wemm ep->l_cur, lno, len); 303b8ba871bSPeter Wemm break; 304b8ba871bSPeter Wemm case LOG_LINE_RESET_F: 305b8ba871bSPeter Wemm TRACE(sp, "%lu: log_line: reset_f: %lu {%u}\n", 306b8ba871bSPeter Wemm ep->l_cur, lno, len); 307b8ba871bSPeter Wemm break; 308b8ba871bSPeter Wemm case LOG_LINE_RESET_B: 309b8ba871bSPeter Wemm TRACE(sp, "%lu: log_line: reset_b: %lu {%u}\n", 310b8ba871bSPeter Wemm ep->l_cur, lno, len); 311b8ba871bSPeter Wemm break; 312b8ba871bSPeter Wemm } 313b8ba871bSPeter Wemm #endif 314b8ba871bSPeter Wemm /* Reset high water mark. */ 315b8ba871bSPeter Wemm ep->l_high = ++ep->l_cur; 316b8ba871bSPeter Wemm 317b8ba871bSPeter Wemm return (0); 318b8ba871bSPeter Wemm } 319b8ba871bSPeter Wemm 320b8ba871bSPeter Wemm /* 321b8ba871bSPeter Wemm * log_mark -- 322b8ba871bSPeter Wemm * Log a mark position. For the log to work, we assume that there 323b8ba871bSPeter Wemm * aren't any operations that just put out a log record -- this 324b8ba871bSPeter Wemm * would mean that undo operations would only reset marks, and not 325b8ba871bSPeter Wemm * cause any other change. 326b8ba871bSPeter Wemm * 327*c271fa92SBaptiste Daroussin * PUBLIC: int log_mark(SCR *, LMARK *); 328b8ba871bSPeter Wemm */ 329b8ba871bSPeter Wemm int 330f0957ccaSPeter Wemm log_mark( 331f0957ccaSPeter Wemm SCR *sp, 332f0957ccaSPeter Wemm LMARK *lmp) 333b8ba871bSPeter Wemm { 334b8ba871bSPeter Wemm DBT data, key; 335b8ba871bSPeter Wemm EXF *ep; 336b8ba871bSPeter Wemm 337b8ba871bSPeter Wemm ep = sp->ep; 338b8ba871bSPeter Wemm if (F_ISSET(ep, F_NOLOG)) 339b8ba871bSPeter Wemm return (0); 340b8ba871bSPeter Wemm 341b8ba871bSPeter Wemm /* Put out one initial cursor record per set of changes. */ 342b8ba871bSPeter Wemm if (ep->l_cursor.lno != OOBLNO) { 343b8ba871bSPeter Wemm if (log_cursor1(sp, LOG_CURSOR_INIT)) 344b8ba871bSPeter Wemm return (1); 345b8ba871bSPeter Wemm ep->l_cursor.lno = OOBLNO; 346b8ba871bSPeter Wemm } 347b8ba871bSPeter Wemm 348f0957ccaSPeter Wemm BINC_RETC(sp, ep->l_lp, 349b8ba871bSPeter Wemm ep->l_len, sizeof(u_char) + sizeof(LMARK)); 350b8ba871bSPeter Wemm ep->l_lp[0] = LOG_MARK; 351b8ba871bSPeter Wemm memmove(ep->l_lp + sizeof(u_char), lmp, sizeof(LMARK)); 352b8ba871bSPeter Wemm 353b8ba871bSPeter Wemm key.data = &ep->l_cur; 354b8ba871bSPeter Wemm key.size = sizeof(recno_t); 355b8ba871bSPeter Wemm data.data = ep->l_lp; 356b8ba871bSPeter Wemm data.size = sizeof(u_char) + sizeof(LMARK); 357b8ba871bSPeter Wemm if (ep->log->put(ep->log, &key, &data, 0) == -1) 358b8ba871bSPeter Wemm LOG_ERR; 359b8ba871bSPeter Wemm 360b8ba871bSPeter Wemm #if defined(DEBUG) && 0 361b8ba871bSPeter Wemm TRACE(sp, "%lu: mark %c: %lu/%u\n", 362b8ba871bSPeter Wemm ep->l_cur, lmp->name, lmp->lno, lmp->cno); 363b8ba871bSPeter Wemm #endif 364b8ba871bSPeter Wemm /* Reset high water mark. */ 365b8ba871bSPeter Wemm ep->l_high = ++ep->l_cur; 366b8ba871bSPeter Wemm return (0); 367b8ba871bSPeter Wemm } 368b8ba871bSPeter Wemm 369b8ba871bSPeter Wemm /* 370b8ba871bSPeter Wemm * Log_backward -- 371b8ba871bSPeter Wemm * Roll the log backward one operation. 372b8ba871bSPeter Wemm * 373*c271fa92SBaptiste Daroussin * PUBLIC: int log_backward(SCR *, MARK *); 374b8ba871bSPeter Wemm */ 375b8ba871bSPeter Wemm int 376f0957ccaSPeter Wemm log_backward( 377f0957ccaSPeter Wemm SCR *sp, 378f0957ccaSPeter Wemm MARK *rp) 379b8ba871bSPeter Wemm { 380b8ba871bSPeter Wemm DBT key, data; 381b8ba871bSPeter Wemm EXF *ep; 382b8ba871bSPeter Wemm LMARK lm; 383b8ba871bSPeter Wemm MARK m; 384b8ba871bSPeter Wemm recno_t lno; 385b8ba871bSPeter Wemm int didop; 386b8ba871bSPeter Wemm u_char *p; 387b8ba871bSPeter Wemm 388b8ba871bSPeter Wemm ep = sp->ep; 389b8ba871bSPeter Wemm if (F_ISSET(ep, F_NOLOG)) { 390b8ba871bSPeter Wemm msgq(sp, M_ERR, 391b8ba871bSPeter Wemm "010|Logging not being performed, undo not possible"); 392b8ba871bSPeter Wemm return (1); 393b8ba871bSPeter Wemm } 394b8ba871bSPeter Wemm 395b8ba871bSPeter Wemm if (ep->l_cur == 1) { 396b8ba871bSPeter Wemm msgq(sp, M_BERR, "011|No changes to undo"); 397b8ba871bSPeter Wemm return (1); 398b8ba871bSPeter Wemm } 399b8ba871bSPeter Wemm 400b8ba871bSPeter Wemm F_SET(ep, F_NOLOG); /* Turn off logging. */ 401b8ba871bSPeter Wemm 402b8ba871bSPeter Wemm key.data = &ep->l_cur; /* Initialize db request. */ 403b8ba871bSPeter Wemm key.size = sizeof(recno_t); 404b8ba871bSPeter Wemm for (didop = 0;;) { 405b8ba871bSPeter Wemm --ep->l_cur; 406b8ba871bSPeter Wemm if (ep->log->get(ep->log, &key, &data, 0)) 407b8ba871bSPeter Wemm LOG_ERR; 408b8ba871bSPeter Wemm #if defined(DEBUG) && 0 409b8ba871bSPeter Wemm log_trace(sp, "log_backward", ep->l_cur, data.data); 410b8ba871bSPeter Wemm #endif 411b8ba871bSPeter Wemm switch (*(p = (u_char *)data.data)) { 412b8ba871bSPeter Wemm case LOG_CURSOR_INIT: 413b8ba871bSPeter Wemm if (didop) { 414b8ba871bSPeter Wemm memmove(rp, p + sizeof(u_char), sizeof(MARK)); 415b8ba871bSPeter Wemm F_CLR(ep, F_NOLOG); 416b8ba871bSPeter Wemm return (0); 417b8ba871bSPeter Wemm } 418b8ba871bSPeter Wemm break; 419b8ba871bSPeter Wemm case LOG_CURSOR_END: 420b8ba871bSPeter Wemm break; 421b8ba871bSPeter Wemm case LOG_LINE_APPEND: 422b8ba871bSPeter Wemm case LOG_LINE_INSERT: 423b8ba871bSPeter Wemm didop = 1; 424b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 425b8ba871bSPeter Wemm if (db_delete(sp, lno)) 426b8ba871bSPeter Wemm goto err; 427b8ba871bSPeter Wemm ++sp->rptlines[L_DELETED]; 428b8ba871bSPeter Wemm break; 429b8ba871bSPeter Wemm case LOG_LINE_DELETE: 430b8ba871bSPeter Wemm didop = 1; 431b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 432f0957ccaSPeter Wemm if (apply_with(db_insert, sp, lno, 433f0957ccaSPeter Wemm p + CHAR_T_OFFSET, data.size - CHAR_T_OFFSET)) 434b8ba871bSPeter Wemm goto err; 435b8ba871bSPeter Wemm ++sp->rptlines[L_ADDED]; 436b8ba871bSPeter Wemm break; 437b8ba871bSPeter Wemm case LOG_LINE_RESET_F: 438b8ba871bSPeter Wemm break; 439b8ba871bSPeter Wemm case LOG_LINE_RESET_B: 440b8ba871bSPeter Wemm didop = 1; 441b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 442f0957ccaSPeter Wemm if (apply_with(db_set, sp, lno, 443f0957ccaSPeter Wemm p + CHAR_T_OFFSET, data.size - CHAR_T_OFFSET)) 444b8ba871bSPeter Wemm goto err; 445b8ba871bSPeter Wemm if (sp->rptlchange != lno) { 446b8ba871bSPeter Wemm sp->rptlchange = lno; 447b8ba871bSPeter Wemm ++sp->rptlines[L_CHANGED]; 448b8ba871bSPeter Wemm } 449b8ba871bSPeter Wemm break; 450b8ba871bSPeter Wemm case LOG_MARK: 451b8ba871bSPeter Wemm didop = 1; 452b8ba871bSPeter Wemm memmove(&lm, p + sizeof(u_char), sizeof(LMARK)); 453b8ba871bSPeter Wemm m.lno = lm.lno; 454b8ba871bSPeter Wemm m.cno = lm.cno; 455b8ba871bSPeter Wemm if (mark_set(sp, lm.name, &m, 0)) 456b8ba871bSPeter Wemm goto err; 457b8ba871bSPeter Wemm break; 458b8ba871bSPeter Wemm default: 459b8ba871bSPeter Wemm abort(); 460b8ba871bSPeter Wemm } 461b8ba871bSPeter Wemm } 462b8ba871bSPeter Wemm 463b8ba871bSPeter Wemm err: F_CLR(ep, F_NOLOG); 464b8ba871bSPeter Wemm return (1); 465b8ba871bSPeter Wemm } 466b8ba871bSPeter Wemm 467b8ba871bSPeter Wemm /* 468b8ba871bSPeter Wemm * Log_setline -- 469b8ba871bSPeter Wemm * Reset the line to its original appearance. 470b8ba871bSPeter Wemm * 471b8ba871bSPeter Wemm * XXX 472b8ba871bSPeter Wemm * There's a bug in this code due to our not logging cursor movements 473b8ba871bSPeter Wemm * unless a change was made. If you do a change, move off the line, 474b8ba871bSPeter Wemm * then move back on and do a 'U', the line will be restored to the way 475b8ba871bSPeter Wemm * it was before the original change. 476b8ba871bSPeter Wemm * 477*c271fa92SBaptiste Daroussin * PUBLIC: int log_setline(SCR *); 478b8ba871bSPeter Wemm */ 479b8ba871bSPeter Wemm int 480f0957ccaSPeter Wemm log_setline(SCR *sp) 481b8ba871bSPeter Wemm { 482b8ba871bSPeter Wemm DBT key, data; 483b8ba871bSPeter Wemm EXF *ep; 484b8ba871bSPeter Wemm LMARK lm; 485b8ba871bSPeter Wemm MARK m; 486b8ba871bSPeter Wemm recno_t lno; 487b8ba871bSPeter Wemm u_char *p; 488b8ba871bSPeter Wemm 489b8ba871bSPeter Wemm ep = sp->ep; 490b8ba871bSPeter Wemm if (F_ISSET(ep, F_NOLOG)) { 491b8ba871bSPeter Wemm msgq(sp, M_ERR, 492b8ba871bSPeter Wemm "012|Logging not being performed, undo not possible"); 493b8ba871bSPeter Wemm return (1); 494b8ba871bSPeter Wemm } 495b8ba871bSPeter Wemm 496b8ba871bSPeter Wemm if (ep->l_cur == 1) 497b8ba871bSPeter Wemm return (1); 498b8ba871bSPeter Wemm 499b8ba871bSPeter Wemm F_SET(ep, F_NOLOG); /* Turn off logging. */ 500b8ba871bSPeter Wemm 501b8ba871bSPeter Wemm key.data = &ep->l_cur; /* Initialize db request. */ 502b8ba871bSPeter Wemm key.size = sizeof(recno_t); 503b8ba871bSPeter Wemm for (;;) { 504b8ba871bSPeter Wemm --ep->l_cur; 505b8ba871bSPeter Wemm if (ep->log->get(ep->log, &key, &data, 0)) 506b8ba871bSPeter Wemm LOG_ERR; 507b8ba871bSPeter Wemm #if defined(DEBUG) && 0 508b8ba871bSPeter Wemm log_trace(sp, "log_setline", ep->l_cur, data.data); 509b8ba871bSPeter Wemm #endif 510b8ba871bSPeter Wemm switch (*(p = (u_char *)data.data)) { 511b8ba871bSPeter Wemm case LOG_CURSOR_INIT: 512b8ba871bSPeter Wemm memmove(&m, p + sizeof(u_char), sizeof(MARK)); 513b8ba871bSPeter Wemm if (m.lno != sp->lno || ep->l_cur == 1) { 514b8ba871bSPeter Wemm F_CLR(ep, F_NOLOG); 515b8ba871bSPeter Wemm return (0); 516b8ba871bSPeter Wemm } 517b8ba871bSPeter Wemm break; 518b8ba871bSPeter Wemm case LOG_CURSOR_END: 519b8ba871bSPeter Wemm memmove(&m, p + sizeof(u_char), sizeof(MARK)); 520b8ba871bSPeter Wemm if (m.lno != sp->lno) { 521b8ba871bSPeter Wemm ++ep->l_cur; 522b8ba871bSPeter Wemm F_CLR(ep, F_NOLOG); 523b8ba871bSPeter Wemm return (0); 524b8ba871bSPeter Wemm } 525b8ba871bSPeter Wemm break; 526b8ba871bSPeter Wemm case LOG_LINE_APPEND: 527b8ba871bSPeter Wemm case LOG_LINE_INSERT: 528b8ba871bSPeter Wemm case LOG_LINE_DELETE: 529b8ba871bSPeter Wemm case LOG_LINE_RESET_F: 530b8ba871bSPeter Wemm break; 531b8ba871bSPeter Wemm case LOG_LINE_RESET_B: 532b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 533b8ba871bSPeter Wemm if (lno == sp->lno && 534f0957ccaSPeter Wemm apply_with(db_set, sp, lno, 535f0957ccaSPeter Wemm p + CHAR_T_OFFSET, data.size - CHAR_T_OFFSET)) 536b8ba871bSPeter Wemm goto err; 537b8ba871bSPeter Wemm if (sp->rptlchange != lno) { 538b8ba871bSPeter Wemm sp->rptlchange = lno; 539b8ba871bSPeter Wemm ++sp->rptlines[L_CHANGED]; 540b8ba871bSPeter Wemm } 541b8ba871bSPeter Wemm case LOG_MARK: 542b8ba871bSPeter Wemm memmove(&lm, p + sizeof(u_char), sizeof(LMARK)); 543b8ba871bSPeter Wemm m.lno = lm.lno; 544b8ba871bSPeter Wemm m.cno = lm.cno; 545b8ba871bSPeter Wemm if (mark_set(sp, lm.name, &m, 0)) 546b8ba871bSPeter Wemm goto err; 547b8ba871bSPeter Wemm break; 548b8ba871bSPeter Wemm default: 549b8ba871bSPeter Wemm abort(); 550b8ba871bSPeter Wemm } 551b8ba871bSPeter Wemm } 552b8ba871bSPeter Wemm 553b8ba871bSPeter Wemm err: F_CLR(ep, F_NOLOG); 554b8ba871bSPeter Wemm return (1); 555b8ba871bSPeter Wemm } 556b8ba871bSPeter Wemm 557b8ba871bSPeter Wemm /* 558b8ba871bSPeter Wemm * Log_forward -- 559b8ba871bSPeter Wemm * Roll the log forward one operation. 560b8ba871bSPeter Wemm * 561*c271fa92SBaptiste Daroussin * PUBLIC: int log_forward(SCR *, MARK *); 562b8ba871bSPeter Wemm */ 563b8ba871bSPeter Wemm int 564f0957ccaSPeter Wemm log_forward( 565f0957ccaSPeter Wemm SCR *sp, 566f0957ccaSPeter Wemm MARK *rp) 567b8ba871bSPeter Wemm { 568b8ba871bSPeter Wemm DBT key, data; 569b8ba871bSPeter Wemm EXF *ep; 570b8ba871bSPeter Wemm LMARK lm; 571b8ba871bSPeter Wemm MARK m; 572b8ba871bSPeter Wemm recno_t lno; 573b8ba871bSPeter Wemm int didop; 574b8ba871bSPeter Wemm u_char *p; 575b8ba871bSPeter Wemm 576b8ba871bSPeter Wemm ep = sp->ep; 577b8ba871bSPeter Wemm if (F_ISSET(ep, F_NOLOG)) { 578b8ba871bSPeter Wemm msgq(sp, M_ERR, 579b8ba871bSPeter Wemm "013|Logging not being performed, roll-forward not possible"); 580b8ba871bSPeter Wemm return (1); 581b8ba871bSPeter Wemm } 582b8ba871bSPeter Wemm 583b8ba871bSPeter Wemm if (ep->l_cur == ep->l_high) { 584b8ba871bSPeter Wemm msgq(sp, M_BERR, "014|No changes to re-do"); 585b8ba871bSPeter Wemm return (1); 586b8ba871bSPeter Wemm } 587b8ba871bSPeter Wemm 588b8ba871bSPeter Wemm F_SET(ep, F_NOLOG); /* Turn off logging. */ 589b8ba871bSPeter Wemm 590b8ba871bSPeter Wemm key.data = &ep->l_cur; /* Initialize db request. */ 591b8ba871bSPeter Wemm key.size = sizeof(recno_t); 592b8ba871bSPeter Wemm for (didop = 0;;) { 593b8ba871bSPeter Wemm ++ep->l_cur; 594b8ba871bSPeter Wemm if (ep->log->get(ep->log, &key, &data, 0)) 595b8ba871bSPeter Wemm LOG_ERR; 596b8ba871bSPeter Wemm #if defined(DEBUG) && 0 597b8ba871bSPeter Wemm log_trace(sp, "log_forward", ep->l_cur, data.data); 598b8ba871bSPeter Wemm #endif 599b8ba871bSPeter Wemm switch (*(p = (u_char *)data.data)) { 600b8ba871bSPeter Wemm case LOG_CURSOR_END: 601b8ba871bSPeter Wemm if (didop) { 602b8ba871bSPeter Wemm ++ep->l_cur; 603b8ba871bSPeter Wemm memmove(rp, p + sizeof(u_char), sizeof(MARK)); 604b8ba871bSPeter Wemm F_CLR(ep, F_NOLOG); 605b8ba871bSPeter Wemm return (0); 606b8ba871bSPeter Wemm } 607b8ba871bSPeter Wemm break; 608b8ba871bSPeter Wemm case LOG_CURSOR_INIT: 609b8ba871bSPeter Wemm break; 610b8ba871bSPeter Wemm case LOG_LINE_APPEND: 611b8ba871bSPeter Wemm case LOG_LINE_INSERT: 612b8ba871bSPeter Wemm didop = 1; 613b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 614f0957ccaSPeter Wemm if (apply_with(db_insert, sp, lno, 615f0957ccaSPeter Wemm p + CHAR_T_OFFSET, data.size - CHAR_T_OFFSET)) 616b8ba871bSPeter Wemm goto err; 617b8ba871bSPeter Wemm ++sp->rptlines[L_ADDED]; 618b8ba871bSPeter Wemm break; 619b8ba871bSPeter Wemm case LOG_LINE_DELETE: 620b8ba871bSPeter Wemm didop = 1; 621b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 622b8ba871bSPeter Wemm if (db_delete(sp, lno)) 623b8ba871bSPeter Wemm goto err; 624b8ba871bSPeter Wemm ++sp->rptlines[L_DELETED]; 625b8ba871bSPeter Wemm break; 626b8ba871bSPeter Wemm case LOG_LINE_RESET_B: 627b8ba871bSPeter Wemm break; 628b8ba871bSPeter Wemm case LOG_LINE_RESET_F: 629b8ba871bSPeter Wemm didop = 1; 630b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 631f0957ccaSPeter Wemm if (apply_with(db_set, sp, lno, 632f0957ccaSPeter Wemm p + CHAR_T_OFFSET, data.size - CHAR_T_OFFSET)) 633b8ba871bSPeter Wemm goto err; 634b8ba871bSPeter Wemm if (sp->rptlchange != lno) { 635b8ba871bSPeter Wemm sp->rptlchange = lno; 636b8ba871bSPeter Wemm ++sp->rptlines[L_CHANGED]; 637b8ba871bSPeter Wemm } 638b8ba871bSPeter Wemm break; 639b8ba871bSPeter Wemm case LOG_MARK: 640b8ba871bSPeter Wemm didop = 1; 641b8ba871bSPeter Wemm memmove(&lm, p + sizeof(u_char), sizeof(LMARK)); 642b8ba871bSPeter Wemm m.lno = lm.lno; 643b8ba871bSPeter Wemm m.cno = lm.cno; 644b8ba871bSPeter Wemm if (mark_set(sp, lm.name, &m, 0)) 645b8ba871bSPeter Wemm goto err; 646b8ba871bSPeter Wemm break; 647b8ba871bSPeter Wemm default: 648b8ba871bSPeter Wemm abort(); 649b8ba871bSPeter Wemm } 650b8ba871bSPeter Wemm } 651b8ba871bSPeter Wemm 652b8ba871bSPeter Wemm err: F_CLR(ep, F_NOLOG); 653b8ba871bSPeter Wemm return (1); 654b8ba871bSPeter Wemm } 655b8ba871bSPeter Wemm 656b8ba871bSPeter Wemm /* 657b8ba871bSPeter Wemm * log_err -- 658b8ba871bSPeter Wemm * Try and restart the log on failure, i.e. if we run out of memory. 659b8ba871bSPeter Wemm */ 660b8ba871bSPeter Wemm static void 661f0957ccaSPeter Wemm log_err( 662f0957ccaSPeter Wemm SCR *sp, 663f0957ccaSPeter Wemm char *file, 664f0957ccaSPeter Wemm int line) 665b8ba871bSPeter Wemm { 666b8ba871bSPeter Wemm EXF *ep; 667b8ba871bSPeter Wemm 668b8ba871bSPeter Wemm msgq(sp, M_SYSERR, "015|%s/%d: log put error", tail(file), line); 669b8ba871bSPeter Wemm ep = sp->ep; 670b8ba871bSPeter Wemm (void)ep->log->close(ep->log); 671b8ba871bSPeter Wemm if (!log_init(sp, ep)) 672b8ba871bSPeter Wemm msgq(sp, M_ERR, "267|Log restarted"); 673b8ba871bSPeter Wemm } 674b8ba871bSPeter Wemm 675b8ba871bSPeter Wemm #if defined(DEBUG) && 0 676b8ba871bSPeter Wemm static void 677f0957ccaSPeter Wemm log_trace( 678f0957ccaSPeter Wemm SCR *sp, 679f0957ccaSPeter Wemm char *msg, 680f0957ccaSPeter Wemm recno_t rno, 681f0957ccaSPeter Wemm u_char *p) 682b8ba871bSPeter Wemm { 683b8ba871bSPeter Wemm LMARK lm; 684b8ba871bSPeter Wemm MARK m; 685b8ba871bSPeter Wemm recno_t lno; 686b8ba871bSPeter Wemm 687b8ba871bSPeter Wemm switch (*p) { 688b8ba871bSPeter Wemm case LOG_CURSOR_INIT: 689b8ba871bSPeter Wemm memmove(&m, p + sizeof(u_char), sizeof(MARK)); 690b8ba871bSPeter Wemm TRACE(sp, "%lu: %s: C_INIT: %u/%u\n", rno, msg, m.lno, m.cno); 691b8ba871bSPeter Wemm break; 692b8ba871bSPeter Wemm case LOG_CURSOR_END: 693b8ba871bSPeter Wemm memmove(&m, p + sizeof(u_char), sizeof(MARK)); 694b8ba871bSPeter Wemm TRACE(sp, "%lu: %s: C_END: %u/%u\n", rno, msg, m.lno, m.cno); 695b8ba871bSPeter Wemm break; 696b8ba871bSPeter Wemm case LOG_LINE_APPEND: 697b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 698b8ba871bSPeter Wemm TRACE(sp, "%lu: %s: APPEND: %lu\n", rno, msg, lno); 699b8ba871bSPeter Wemm break; 700b8ba871bSPeter Wemm case LOG_LINE_INSERT: 701b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 702b8ba871bSPeter Wemm TRACE(sp, "%lu: %s: INSERT: %lu\n", rno, msg, lno); 703b8ba871bSPeter Wemm break; 704b8ba871bSPeter Wemm case LOG_LINE_DELETE: 705b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 706b8ba871bSPeter Wemm TRACE(sp, "%lu: %s: DELETE: %lu\n", rno, msg, lno); 707b8ba871bSPeter Wemm break; 708b8ba871bSPeter Wemm case LOG_LINE_RESET_F: 709b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 710b8ba871bSPeter Wemm TRACE(sp, "%lu: %s: RESET_F: %lu\n", rno, msg, lno); 711b8ba871bSPeter Wemm break; 712b8ba871bSPeter Wemm case LOG_LINE_RESET_B: 713b8ba871bSPeter Wemm memmove(&lno, p + sizeof(u_char), sizeof(recno_t)); 714b8ba871bSPeter Wemm TRACE(sp, "%lu: %s: RESET_B: %lu\n", rno, msg, lno); 715b8ba871bSPeter Wemm break; 716b8ba871bSPeter Wemm case LOG_MARK: 717b8ba871bSPeter Wemm memmove(&lm, p + sizeof(u_char), sizeof(LMARK)); 718b8ba871bSPeter Wemm TRACE(sp, 719b8ba871bSPeter Wemm "%lu: %s: MARK: %u/%u\n", rno, msg, lm.lno, lm.cno); 720b8ba871bSPeter Wemm break; 721b8ba871bSPeter Wemm default: 722b8ba871bSPeter Wemm abort(); 723b8ba871bSPeter Wemm } 724b8ba871bSPeter Wemm } 725b8ba871bSPeter Wemm #endif 726f0957ccaSPeter Wemm 727f0957ccaSPeter Wemm /* 728f0957ccaSPeter Wemm * apply_with -- 729f0957ccaSPeter Wemm * Apply a realigned line from the log db to the file db. 730f0957ccaSPeter Wemm */ 731f0957ccaSPeter Wemm static int 732f0957ccaSPeter Wemm apply_with( 733f0957ccaSPeter Wemm int (*db_func)(SCR *, recno_t, CHAR_T *, size_t), 734f0957ccaSPeter Wemm SCR *sp, 735f0957ccaSPeter Wemm recno_t lno, 736f0957ccaSPeter Wemm u_char *p, 737f0957ccaSPeter Wemm size_t len) 738f0957ccaSPeter Wemm { 739f0957ccaSPeter Wemm #ifdef USE_WIDECHAR 740f0957ccaSPeter Wemm typedef unsigned long nword; 741f0957ccaSPeter Wemm 742f0957ccaSPeter Wemm static size_t blen; 743f0957ccaSPeter Wemm static nword *bp; 744f0957ccaSPeter Wemm nword *lp = (nword *)((uintptr_t)p / sizeof(nword) * sizeof(nword)); 745f0957ccaSPeter Wemm 746f0957ccaSPeter Wemm if (lp != (nword *)p) { 747f0957ccaSPeter Wemm int offl = ((uintptr_t)p - (uintptr_t)lp) << 3; 748f0957ccaSPeter Wemm int offr = (sizeof(nword) << 3) - offl; 749f0957ccaSPeter Wemm size_t i, cnt = (len + sizeof(nword) / 2) / sizeof(nword); 750f0957ccaSPeter Wemm 751f0957ccaSPeter Wemm if (len > blen) { 752f0957ccaSPeter Wemm blen = p2roundup(MAX(len, 512)); 753f0957ccaSPeter Wemm REALLOC(sp, bp, nword *, blen); 754f0957ccaSPeter Wemm if (bp == NULL) 755f0957ccaSPeter Wemm return (1); 756f0957ccaSPeter Wemm } 757f0957ccaSPeter Wemm for (i = 0; i < cnt; ++i) 758f0957ccaSPeter Wemm #if BYTE_ORDER == BIG_ENDIAN 759f0957ccaSPeter Wemm bp[i] = (lp[i] << offl) ^ (lp[i+1] >> offr); 760f0957ccaSPeter Wemm #else 761f0957ccaSPeter Wemm bp[i] = (lp[i] >> offl) ^ (lp[i+1] << offr); 762f0957ccaSPeter Wemm #endif 763f0957ccaSPeter Wemm p = (u_char *)bp; 764f0957ccaSPeter Wemm } 765f0957ccaSPeter Wemm #endif 766f0957ccaSPeter Wemm return db_func(sp, lno, (CHAR_T *)p, len / sizeof(CHAR_T)); 767f0957ccaSPeter Wemm } 768