1/*
2  This file contains some routines that are #ifdef'ed based on what
3  system you're on.  Currently it supports the BeOS and Unix. It
4  could be extended to support Windows NT but their posix support
5  is such a joke that it would probably be a real pain in the arse.
6
7  THIS CODE COPYRIGHT DOMINIC GIAMPAOLO.  NO WARRANTY IS EXPRESSED
8  OR IMPLIED.  YOU MAY USE THIS CODE AND FREELY DISTRIBUTE IT FOR
9  NON-COMMERCIAL USE AS LONG AS THIS NOTICE REMAINS ATTACHED.
10
11  FOR COMMERCIAL USE, CONTACT DOMINIC GIAMPAOLO (dbg@be.com).
12
13  Dominic Giampaolo
14  dbg@be.com
15*/
16#include <stdio.h>
17#include <fcntl.h>
18#include <unistd.h>
19#include <sys/stat.h>
20
21#include "compat.h"
22
23
24int
25device_is_read_only(const char *device)
26{
27#ifdef unix
28    return 0;   /* XXXdbg should do an ioctl or something */
29#else
30    int             fd;
31    device_geometry dg;
32
33    fd = open(device, O_RDONLY);
34    if (ioctl(fd, B_GET_GEOMETRY, &dg) < 0)
35        return 0;
36
37    close(fd);
38
39    return dg.read_only;
40#endif
41}
42
43int
44get_device_block_size(int fd)
45{
46#ifdef unix
47    return 512;   /* XXXdbg should do an ioctl or something */
48#else
49    struct stat     st;
50    device_geometry dg;
51
52    if (ioctl(fd, B_GET_GEOMETRY, &dg) < 0) {
53        if (fstat(fd, &st) < 0 || S_ISDIR(st.st_mode))
54            return 0;
55
56        return 512;   /* just assume it's a plain old file or something */
57    }
58
59    return dg.bytes_per_sector;
60#endif
61}
62
63fs_off_t
64get_num_device_blocks(int fd)
65{
66#ifdef unix
67    struct stat st;
68
69    fstat(fd, &st);    /* XXXdbg should be an ioctl or something */
70
71    return st.st_size / get_device_block_size(fd);
72#else
73    struct stat st;
74    device_geometry dg;
75
76    if (ioctl(fd, B_GET_GEOMETRY, &dg) >= 0) {
77        return (fs_off_t)dg.cylinder_count *
78               (fs_off_t)dg.sectors_per_track *
79               (fs_off_t)dg.head_count;
80    }
81
82    /* if the ioctl fails, try just stat'ing in case it's a regular file */
83    if (fstat(fd, &st) < 0)
84        return 0;
85
86    return st.st_size / get_device_block_size(fd);
87#endif
88}
89
90int
91device_is_removeable(int fd)
92{
93#ifdef unix
94    return 0;   /* XXXdbg should do an ioctl or something */
95#else
96    device_geometry dg;
97
98    if (ioctl(fd, B_GET_GEOMETRY, &dg) < 0) {
99        return 0;
100    }
101
102    return dg.removable;
103#endif
104}
105
106#if (defined(__BEOS__) || defined(__HAIKU__)) && !defined(USER)
107#include "scsi.h"
108#endif
109
110int
111lock_removeable_device(int fd, bool on_or_off)
112{
113#if defined(unix) || defined(USER)
114    return 0;   /* XXXdbg should do an ioctl or something */
115#else
116    return ioctl(fd, B_SCSI_PREVENT_ALLOW, &on_or_off);
117#endif
118}
119
120
121
122
123#if (!defined(__BEOS__) && !defined(__HAIKU__))
124ssize_t
125read_pos(int fd, fs_off_t _pos, void *data,  size_t nbytes)
126{
127    off_t  pos = (off_t)_pos;
128    size_t ret;
129
130    if (lseek(fd, pos, SEEK_SET) < 0) {
131        perror("read lseek");
132        return EINVAL;
133    }
134
135    ret = read(fd, data, nbytes);
136
137    if (ret != nbytes) {
138        printf("read_pos: wanted %d, got %d\n", nbytes, ret);
139        return -1;
140    }
141
142    return ret;
143}
144
145ssize_t
146write_pos(int fd, fs_off_t _pos, const void *data,  size_t nbytes)
147{
148    off_t  pos = (off_t)_pos;
149    size_t ret;
150
151    if (lseek(fd, pos, SEEK_SET) < 0) {
152        perror("read lseek");
153        return EINVAL;
154    }
155
156    ret = write(fd, data, nbytes);
157
158    if (ret != nbytes) {
159        printf("write_pos: wanted %d, got %d\n", nbytes, ret);
160        return -1;
161    }
162
163    return ret;
164}
165
166
167#ifdef sun                      /* bloody wankers */
168#include <sys/stream.h>
169#ifdef DEF_IOV_MAX
170#define MAX_IOV  DEF_IOV_MAX
171#else
172#define MAX_IOV  16
173#endif
174#else                         /* the rest of the world... */
175#define MAX_IOV  8192         /* something way bigger than we'll ever use */
176#endif
177
178ssize_t
179readv_pos(int fd, fs_off_t _pos, struct iovec *iov, int count)
180{
181    off_t  pos = (off_t)_pos;
182    size_t amt = 0;
183    ssize_t ret;
184    struct iovec *tmpiov;
185    int i, n;
186
187    if (lseek(fd, pos, SEEK_SET) < 0) {
188        perror("read lseek");
189        return EINVAL;
190    }
191
192    i = 0;
193    tmpiov = iov;
194    while (i < count) {
195        if (i + MAX_IOV < count)
196            n = MAX_IOV;
197        else
198            n = (count - i);
199
200        ret = readv(fd, tmpiov, n);
201        amt += ret;
202
203        if (ret < 0)
204            break;
205
206        i += n;
207        tmpiov += n;
208    }
209
210    return amt;
211}
212
213ssize_t
214writev_pos(int fd, fs_off_t _pos, struct iovec *iov,  int count)
215{
216    off_t  pos = (off_t)_pos;
217    size_t amt = 0;
218    ssize_t ret;
219    struct iovec *tmpiov;
220    int i, n;
221
222    if (lseek(fd, pos, SEEK_SET) < 0) {
223        perror("read lseek");
224        return EINVAL;
225    }
226
227    i = 0;
228    tmpiov = iov;
229    while (i < count) {
230        if (i + MAX_IOV < count)
231            n = MAX_IOV;
232        else
233            n = (count - i);
234
235        ret = writev(fd, tmpiov, n);
236        amt += ret;
237
238        if (ret < 0)
239            break;
240
241        i += n;
242        tmpiov += n;
243    }
244
245    return amt;
246}
247
248
249
250#endif /* __BEOS__ */
251
252
253#include <stdarg.h>
254
255
256#if 0	// bonefish
257void
258panic(const char *format, ...)
259{
260    va_list     ap;
261
262    va_start(ap, format);
263    vfprintf(stderr, format, ap);
264    va_end(ap);
265
266    while (TRUE)
267        ;
268}
269#endif
270
271
272#include "lock.h"
273
274int
275new_lock(lock *l, const char *name)
276{
277    l->c = 1;
278    l->s = create_sem(0, (char *)name);
279    if (l->s <= 0)
280        return l->s;
281    return 0;
282}
283
284int
285free_lock(lock *l)
286{
287    delete_sem(l->s);
288
289    return 0;
290}
291
292int
293new_mlock(mlock *l, long c, const char *name)
294{
295    l->s = create_sem(c, (char *)name);
296    if (l->s <= 0)
297        return l->s;
298    return 0;
299}
300
301int
302free_mlock(mlock *l)
303{
304    delete_sem(l->s);
305
306    return 0;
307}
308
309
310#ifdef unix
311#include <sys/time.h>
312
313bigtime_t
314system_time(void)
315{
316    bigtime_t      t;
317    struct timeval tv;
318
319    gettimeofday(&tv, NULL);
320
321    t = ((bigtime_t)tv.tv_sec * 1000000) + (bigtime_t)tv.tv_usec;
322    return t;
323}
324
325/*
326  If you're compiler/system can't deal with the version of system_time()
327  as defined above, use this one instead
328bigtime_t
329system_time(void)
330{
331    return (bigtime_t)time(NULL);
332}
333*/
334
335#endif  /* unix */
336
337#if (defined(__BEOS__) || defined(__HAIKU__))
338#include <KernelExport.h>
339
340void
341dprintf(const char *format, ...)
342{
343	va_list args;
344
345	va_start(args, format);
346	vprintf(format, args);
347	va_end(args);
348}
349
350#endif
351