1/*	$NetBSD: riscosfile.c,v 1.3 2005/12/11 12:16:08 christos Exp $	*/
2
3/*-
4 * Copyright (c) 2001 Ben Harris
5 * All rights reserved.
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 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission.
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 BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <lib/libsa/stand.h>
31#include <riscoscalls.h>
32#include <riscosfile.h>
33#include <sys/stat.h>
34
35struct riscosfile {
36	int file;
37};
38
39int
40riscos_open(const char *path, struct open_file *f)
41{
42	struct riscosfile *rf;
43	os_error *error;
44	int flags;
45
46	rf = (struct riscosfile *) alloc(sizeof(*rf));
47	if (!rf)
48		return -1;
49
50	switch (f->f_flags & (F_READ | F_WRITE)) {
51	case F_READ:
52		flags = OSFind_Openin;
53		break;
54	case F_WRITE:
55		flags = OSFind_Openout;
56		break;
57	case F_READ | F_WRITE:
58		flags = OSFind_Openup;
59		break;
60	default:
61		/* Erm... */
62		return EINVAL;
63	}
64
65	error = xosfind_open(flags | osfind_ERROR_IF_DIR |
66	    osfind_ERROR_IF_ABSENT, path, NULL, &rf->file);
67	if (error) {
68		dealloc(rf, sizeof(*rf));
69		return riscos_errno(error);
70	}
71	f->f_fsdata = rf;
72	return 0;
73}
74
75#ifndef LIBSA_NO_FS_CLOSE
76int
77riscos_close(struct open_file *f)
78{
79	struct riscosfile *rf;
80	struct os_error *error;
81	int err = 0;
82
83	rf = f->f_fsdata;
84
85	error = xosfind_close(rf->file);
86	if (error)
87		err = riscos_errno(error);
88	dealloc(rf, sizeof(*rf));
89	return err;
90}
91#endif
92
93int
94riscos_read(struct open_file *f, void *buf, size_t size, size_t *residp)
95{
96	struct riscosfile *rf;
97	int resid;
98	os_error *error;
99
100	rf = f->f_fsdata;
101
102#ifndef LIBSA_NO_TWIDDLE
103	twiddle();
104#endif
105	error = xosgbpb_read(rf->file, buf, size, &resid);
106	*residp = resid;
107	if (error)
108		return riscos_errno(error);
109	return 0;
110}
111
112#ifndef LIBSA_NO_FS_WRITE
113int
114riscos_write(struct open_file *f, void *buf, size_t size, size_t *residp)
115{
116	struct riscosfile *rf;
117	int resid;
118	os_error *error;
119
120	rf = f->f_fsdata;
121
122#ifndef LIBSA_NO_TWIDDLE
123	twiddle();
124#endif
125	error = xosgbpb_write(rf->file, buf, size, &resid);
126	*residp = resid;
127	if (error)
128		return riscos_errno(error);
129	return 0;
130}
131#endif
132
133int
134riscos_stat(struct open_file *f, struct stat *sb)
135{
136	struct riscosfile *rf;
137	os_error *error;
138	int extent;
139
140	rf = f->f_fsdata;
141
142	error = xosargs_read_ext(rf->file, &extent);
143	if (error)
144		return riscos_errno(error);
145
146	sb->st_mode = S_IFREG | 0444;
147	sb->st_nlink = 1;
148	sb->st_uid = 0;
149	sb->st_gid = 0;
150	sb->st_size = extent;
151	return 0;
152}
153
154#ifndef LIBSA_NO_FS_SEEK
155off_t
156riscos_seek(struct open_file *f, off_t offset, int where)
157{
158	struct riscosfile *rf;
159	int base, result;
160	os_error *error;
161
162	rf = f->f_fsdata;
163
164	switch (where) {
165	case SEEK_SET:
166		base = 0;
167		break;
168	case SEEK_CUR:
169		error = xosargs_read_ptr(rf->file, &base);
170		if (error)
171			goto err;
172		break;
173	case SEEK_END:
174		error = xosargs_read_ext(rf->file, &base);
175		if (error)
176			goto err;
177		break;
178	default:
179		errno = EOFFSET;
180		return -1;
181	}
182	offset = base + offset;
183	error = xosargs_set_ptr(rf->file, offset);
184	if (error)
185		goto err;
186	error = xosargs_read_ptr(rf->file, &result);
187	if (error)
188		goto err;
189	return result;
190
191err:
192	errno = riscos_errno(error);
193	return -1;
194}
195#endif
196