xref: /netbsd/sys/arch/hppa/stand/common/lif.c (revision 9c866379)
1 /*	$NetBSD: lif.c,v 1.2 2018/09/04 15:08:30 riastradh Exp $	*/
2 
3 /*	$OpenBSD: lif.c,v 1.7 2001/06/09 03:54:41 mickey Exp $	*/
4 
5 /*
6  * Copyright (c) 1998-2004 Michael Shalayeff
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/disklabel.h>
33 #include "libsa.h"
34 
35 extern int debug;
36 
37 struct file {
38 	char f_buf[HPPA_LIF_FILESTART];/* buffer for lif volume header and dir */
39 	struct hppa_lifvol *f_lp;	/* lif volume header pointer */
40 	struct hppa_lifdir *f_ld;	/* lif dir pointer */
41 	int	f_nfiles;	/* gross number for lif dir entries */
42 
43 	off_t	f_seek;		/* seek pointer for file read */
44 	struct hppa_lifdir *f_rd;	/* lif dir pointer for readdir */
45 
46 	int	f_isdir;	/* special hacky flag for '.' dir */
47 	int	f_count;	/* this file length */
48 	int	f_off;		/* this file offset */
49 };
50 
51 int
lif_open(const char * path,struct open_file * f)52 lif_open(const char *path, struct open_file *f)
53 {
54 	struct file *fp;
55 	struct hppa_lifdir *dp;
56 	const char *p, *q;
57 	struct hppa_lifload load;
58 	int err, l;
59 	size_t buf_size;
60 
61 #ifdef LIFDEBUG
62 	if (debug)
63 		printf("lif_open(%s, %p)\n", path, f);
64 #endif
65 
66 	fp = alloc(sizeof(*fp));
67 	/* XXX we're assuming here that sizeof(fp->f_buf) >= HPPA_LIF_FILESTART */
68 
69 	err = (*f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0,
70 	    sizeof(fp->f_buf), &fp->f_buf, &buf_size);
71 	if (err || buf_size != sizeof(fp->f_buf)) {
72 #ifdef LIFDEBUG
73 		if (debug)
74 			printf("lif_open: unable to read LIF header (%d)\n", err);
75 #endif
76 	} else if ((fp->f_lp = (struct hppa_lifvol *)fp->f_buf)->vol_id ==
77 		   HPPA_LIF_VOL_ID) {
78 		f->f_fsdata = fp;
79 		fp->f_ld = (struct hppa_lifdir *)(fp->f_buf + HPPA_LIF_DIRSTART);
80 		fp->f_seek = 0;
81 		fp->f_rd = fp->f_ld;
82 		fp->f_nfiles = hppa_lifstob(fp->f_lp->vol_dirsize) /
83 			sizeof(struct hppa_lifdir);
84 
85 		/* no dirs on the lif */
86 		for (p = path + (l = strlen(path)); p >= path; p--)
87 			if (*p == '/') {
88 				p++;
89 				break;
90 			}
91 		if (p > path)
92 			path = p;
93 	} else
94 		err = EINVAL;
95 
96 	if (!err && *path != '.') {
97 		fp->f_isdir = 0;
98 		err = ENOENT;
99 		for (dp = fp->f_ld; dp < &fp->f_ld[fp->f_nfiles]; dp++) {
100 #ifdef LIFDEBUG
101 			if (debug)
102 				printf("lif_open: "
103 				       "%s <--> '%c%c%c%c%c%c%c%c%c%c'\n",
104 				       path, dp->dir_name[0], dp->dir_name[1],
105 				       dp->dir_name[2], dp->dir_name[3],
106 				       dp->dir_name[4], dp->dir_name[5],
107 				       dp->dir_name[6], dp->dir_name[7],
108 				       dp->dir_name[8], dp->dir_name[9]);
109 #endif
110 			for (p = path, q = dp->dir_name;
111 			     *q && *q != ' '; q++, p++)
112 				if (tolower(*q) != tolower(*p))
113 					break;
114 			if ((!*q || *q == ' ') && !*p) {
115 				err = 0;
116 				break;
117 			}
118 		}
119 		if (!err) {
120 			fp->f_off = hppa_lifstodb(dp->dir_addr);
121 			if (!(err =(f->f_dev->dv_strategy)(f->f_devdata, F_READ,
122 			      fp->f_off, sizeof(load), &load, &buf_size)) &&
123 			    buf_size == sizeof(load)) {
124 				/* no checksum */
125 				fp->f_count = load.count - sizeof(int);
126 				fp->f_off = dbtob(fp->f_off) + sizeof(load);
127 #ifdef LIFDEBUG
128 				if (debug)
129 					printf("lif_open: %u @ %u [%x]\n",
130 					       fp->f_count, fp->f_off,
131 					       load.address);
132 #endif
133 			} else if (!err)
134 				err = EIO;
135 		}
136 	} else
137 		fp->f_isdir = 1;
138 
139 	if (err) {
140 		dealloc (fp, sizeof(*fp));
141 		f->f_fsdata = NULL;
142 	}
143 #ifdef LIFDEBUG
144 	if (debug)
145 		printf("ret(%d)\n", err);
146 #endif
147 	return err;
148 }
149 
150 int
lif_close(struct open_file * f)151 lif_close(struct open_file *f)
152 {
153 	dealloc(f->f_fsdata, sizeof(struct file));
154 	f->f_fsdata = NULL;
155 	return 0;
156 }
157 
158 int
lif_read(struct open_file * f,void * buf,size_t size,size_t * resid)159 lif_read(struct open_file *f, void *buf, size_t size, size_t *resid)
160 {
161 	struct file *fp = (struct file *)f->f_fsdata;
162 	char *p;
163 	char bbuf[DEV_BSIZE];
164 	size_t bsize, count = sizeof(bbuf);
165 	int err = 0;
166 	int foff;
167 
168 #ifdef LIFDEBUG
169 	if (debug)
170 		printf("lif_read(%p, %p, %zu, %p)\n", f, buf, size, resid);
171 #endif
172 
173 	for (p = bbuf; size; fp->f_seek += bsize, p += bsize) {
174 		twiddle();
175 		foff = fp->f_off + fp->f_seek;
176 		if (fp->f_seek >= fp->f_count ||
177 		    (err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
178 		     btodb(foff), count, p, &bsize)))
179 			break;
180 		if (p == bbuf) {
181 			bsize = sizeof(bbuf) - (foff & (sizeof(bbuf) - 1));
182 			bsize = uimin(bsize, size);
183 			memcpy(buf, bbuf + (foff & (sizeof(bbuf) - 1)), bsize);
184 			p = buf;
185 		}
186 		count = size -= bsize;
187 	}
188 	if (resid)
189 		*resid = size;
190 
191 	return err;
192 }
193 
194 int
lif_write(struct open_file * f,void * buf,size_t size,size_t * resid)195 lif_write(struct open_file *f, void *buf, size_t size, size_t *resid)
196 {
197 	return EOPNOTSUPP;
198 }
199 
200 off_t
lif_seek(struct open_file * f,off_t offset,int where)201 lif_seek(struct open_file *f, off_t offset, int where)
202 {
203 	struct file *fp = (struct file *)f->f_fsdata;
204 
205 	switch (where) {
206 	case SEEK_SET:
207 		fp->f_seek = offset;
208 		break;
209 	case SEEK_CUR:
210 		fp->f_seek += offset;
211 		break;
212 	case SEEK_END:
213 		fp->f_seek = fp->f_count - offset;
214 		break;
215 	default:
216 		return (-1);
217 	}
218 	return (fp->f_seek);
219 }
220 
221 int
lif_stat(struct open_file * f,struct stat * sb)222 lif_stat(struct open_file *f, struct stat *sb)
223 {
224 	struct file *fp = (struct file *)f->f_fsdata;
225 
226 	sb->st_mode = 0755 | (fp->f_isdir? S_IFDIR: 0);	/* XXX */
227 	sb->st_uid = 0;
228 	sb->st_gid = 0;
229 	sb->st_size = fp->f_count;
230 	return 0;
231 }
232 
233 int
lif_readdir(struct open_file * f,char * name)234 lif_readdir(struct open_file *f, char *name)
235 {
236 	struct file *fp = (struct file *)f->f_fsdata;
237 	char *p;
238 
239 	if (name) {
240 		while ((fp->f_rd->dir_name[0] == ' ' ||
241 			!fp->f_rd->dir_name[0]) &&
242 		       (fp->f_rd - fp->f_ld) < fp->f_nfiles)
243 			fp->f_rd++;
244 		if ((fp->f_rd - fp->f_ld) >= fp->f_nfiles) {
245 			*name = '\0';
246 			return -1;
247 		}
248 		strncpy(name, fp->f_rd->dir_name, sizeof(fp->f_rd->dir_name));
249 		if ((p = strchr(name, ' ')))
250 			*p = '\0';
251 		fp->f_rd++;
252 	} else
253 		fp->f_rd = fp->f_ld;
254 
255 	return 0;
256 }
257