1 /* 2 * Copyright (c) 2004,2005 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/sbin/jscan/jfile.c,v 1.5 2005/07/06 06:06:44 dillon Exp $ 35 */ 36 37 #include "jscan.h" 38 39 /* 40 * Open a journal for directional scanning 41 */ 42 struct jfile * 43 jopen_stream(const char *path, enum jdirection jdir, int flags) 44 { 45 FILE *fp; 46 struct jfile *jf; 47 48 if ((fp = fopen(path, "r")) == NULL) 49 return (NULL); 50 if ((jf = jopen_fp(fp, jdir, flags)) == NULL) 51 fclose (fp); 52 return(jf); 53 } 54 55 struct jfile * 56 jopen_fp(FILE *fp, enum jdirection jdir, int flags) 57 { 58 struct jfile *jf; 59 60 jf = malloc(sizeof(struct jfile)); 61 bzero(jf, sizeof(struct jfile)); 62 jf->jf_fp = fp; 63 jf->jf_direction = jdir; 64 jf->jf_setpt = -1; 65 jf->jf_flags = flags; 66 if (jdir == JF_BACKWARDS) { 67 fseeko(jf->jf_fp, 0L, SEEK_END); 68 jf->jf_pos = ftello(jf->jf_fp); 69 } 70 return(jf); 71 } 72 73 /* 74 * Close a previously opened journal, clean up any side allocations. 75 */ 76 void 77 jclose_stream(struct jfile *jf) 78 { 79 struct jdata *jd; 80 81 fclose(jf->jf_fp); 82 jf->jf_fp = NULL; 83 while ((jd = jf->jf_saved) != NULL) { 84 jf->jf_saved = jd->jd_next; 85 free(jd); 86 } 87 free(jf); 88 } 89 90 /* 91 * Align us to the next 16 byte boundary. If scanning forwards we align 92 * forwards if not already aligned. If scanning backwards we align 93 * backwards if not already aligned. 94 */ 95 void 96 jalign(struct jfile *jf) 97 { 98 if (jf->jf_direction == JF_FORWARDS) { 99 jf->jf_pos = (jf->jf_pos + 15) & ~15; 100 fseeko(jf->jf_fp, jf->jf_pos, SEEK_SET); 101 } else { 102 jf->jf_pos = jf->jf_pos & ~15; 103 } 104 } 105 106 /* 107 * Read data from a journal forwards or backwards. Note that the file 108 * pointer's actual seek position does not match jf_pos in the reverse 109 * scan case. Callers should never access jf_fp directly. 110 */ 111 int 112 jread(struct jfile *jf, void *buf, int bytes) 113 { 114 int n; 115 116 if (jf->jf_direction == JF_FORWARDS) { 117 while (bytes) { 118 n = fread(buf, 1, bytes, jf->jf_fp); 119 if (n <= 0) 120 break; 121 assert(n <= bytes); 122 jf->jf_pos += n; 123 buf = (char *)buf + n; 124 bytes -= n; 125 } 126 if (bytes == 0) { 127 return (0); 128 } else { 129 fseeko(jf->jf_fp, jf->jf_pos, SEEK_SET); 130 return (errno ? errno : ENOENT); 131 } 132 } else { 133 if (bytes > jf->jf_pos) 134 return (ENOENT); 135 jf->jf_pos -= bytes; 136 fseeko(jf->jf_fp, jf->jf_pos, SEEK_SET); 137 if (fread(buf, bytes, 1, jf->jf_fp) == 1) { 138 return (0); 139 } else { 140 jf->jf_pos += bytes; 141 return (errno); 142 } 143 } 144 } 145 146 int 147 jwrite(struct jfile *jf, void *buf, int bytes) 148 { 149 int n; 150 151 n = write(fileno(jf->jf_fp), buf, bytes); 152 return(n); 153 } 154 155 void 156 jset(struct jfile *jf) 157 { 158 jf->jf_setpt = jf->jf_pos; 159 } 160 161 void 162 jreturn(struct jfile *jf) 163 { 164 jf->jf_pos = jf->jf_setpt; 165 jf->jf_setpt = -1; 166 fseeko(jf->jf_fp, jf->jf_pos, SEEK_SET); 167 } 168 169 void 170 jflush(struct jfile *jf) 171 { 172 jf->jf_setpt = -1; 173 } 174 175