xref: /netbsd-src/external/bsd/pdisk/dist/file_media.c (revision 48a628ae0434c4247b560ad8f2eb1dc06d0dd070)
19428323dSchristos /*
29428323dSchristos  * file_media.c -
39428323dSchristos  *
49428323dSchristos  * Written by Eryk Vershen
59428323dSchristos  */
69428323dSchristos 
79428323dSchristos /*
89428323dSchristos  * Copyright 1997,1998 by Apple Computer, Inc.
99428323dSchristos  *              All Rights Reserved
109428323dSchristos  *
119428323dSchristos  * Permission to use, copy, modify, and distribute this software and
129428323dSchristos  * its documentation for any purpose and without fee is hereby granted,
139428323dSchristos  * provided that the above copyright notice appears in all copies and
149428323dSchristos  * that both the copyright notice and this permission notice appear in
159428323dSchristos  * supporting documentation.
169428323dSchristos  *
179428323dSchristos  * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
189428323dSchristos  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
199428323dSchristos  * FOR A PARTICULAR PURPOSE.
209428323dSchristos  *
219428323dSchristos  * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
229428323dSchristos  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
239428323dSchristos  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
249428323dSchristos  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
259428323dSchristos  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
269428323dSchristos  */
279428323dSchristos 
289428323dSchristos // for printf()
299428323dSchristos #include <stdio.h>
309428323dSchristos // for malloc() & free()
319428323dSchristos #include <stdlib.h>
329428323dSchristos // for lseek(), read(), write(), close()
339428323dSchristos #include <unistd.h>
349428323dSchristos // for open()
359428323dSchristos #include <fcntl.h>
369428323dSchristos // for LONG_MAX
379428323dSchristos #include <limits.h>
389428323dSchristos // for errno
399428323dSchristos #include <errno.h>
409428323dSchristos 
419428323dSchristos #ifdef __linux__
429428323dSchristos #include <sys/ioctl.h>
439428323dSchristos #include <linux/fs.h>
449428323dSchristos #include <linux/hdreg.h>
459428323dSchristos #include <sys/stat.h>
469428323dSchristos #else
479428323dSchristos #ifdef __unix__
489428323dSchristos #include <sys/ioctl.h>
499428323dSchristos #include <sys/stat.h>
509428323dSchristos #endif
519428323dSchristos #endif
529428323dSchristos 
539428323dSchristos #include "file_media.h"
549428323dSchristos #include "errors.h"
559428323dSchristos 
569428323dSchristos 
579428323dSchristos /*
589428323dSchristos  * Defines
599428323dSchristos  */
609428323dSchristos #ifdef __linux__
619428323dSchristos #define LOFF_MAX 9223372036854775807LL
629428323dSchristos extern __loff_t llseek __P ((int __fd, __loff_t __offset, int __whence));
63*48a628aeSchristos #elif defined(__NetBSD__) || defined(__APPLE__)
64*48a628aeSchristos #define loff_t off_t
65*48a628aeSchristos #define llseek lseek
66*48a628aeSchristos #define LOFF_MAX LLONG_MAX
679428323dSchristos #else
689428323dSchristos #define loff_t long
699428323dSchristos #define llseek lseek
709428323dSchristos #define LOFF_MAX LONG_MAX
719428323dSchristos #endif
729428323dSchristos 
739428323dSchristos 
749428323dSchristos /*
759428323dSchristos  * Types
769428323dSchristos  */
779428323dSchristos typedef struct file_media *FILE_MEDIA;
789428323dSchristos 
799428323dSchristos struct file_media {
809428323dSchristos     struct media	m;
819428323dSchristos     int			fd;
829428323dSchristos     int			regular_file;
839428323dSchristos };
849428323dSchristos 
859428323dSchristos struct file_media_globals {
869428323dSchristos     long		exists;
879428323dSchristos     long		kind;
889428323dSchristos };
899428323dSchristos 
909428323dSchristos typedef struct file_media_iterator *FILE_MEDIA_ITERATOR;
919428323dSchristos 
929428323dSchristos struct file_media_iterator {
939428323dSchristos     struct media_iterator   m;
949428323dSchristos     long		    style;
959428323dSchristos     long		    index;
969428323dSchristos };
979428323dSchristos 
989428323dSchristos 
999428323dSchristos /*
1009428323dSchristos  * Global Constants
1019428323dSchristos  */
1029428323dSchristos int potential_block_sizes[] = {
103*48a628aeSchristos     1, 512, 1024, 2048, 4096, 8192, 16834,
1049428323dSchristos     0
1059428323dSchristos };
1069428323dSchristos 
1079428323dSchristos enum {
1089428323dSchristos     kSCSI_Disks = 0,
1099428323dSchristos     kATA_Devices = 1,
1109428323dSchristos     kSCSI_CDs = 2,
1119428323dSchristos     kMaxStyle = 2
1129428323dSchristos };
1139428323dSchristos 
1149428323dSchristos 
1159428323dSchristos /*
1169428323dSchristos  * Global Variables
1179428323dSchristos  */
1189428323dSchristos static long file_inited = 0;
1199428323dSchristos static struct file_media_globals file_info;
1209428323dSchristos 
1219428323dSchristos /*
1229428323dSchristos  * Forward declarations
1239428323dSchristos  */
1249428323dSchristos int compute_block_size(int fd);
1259428323dSchristos void file_init(void);
1269428323dSchristos FILE_MEDIA new_file_media(void);
127*48a628aeSchristos long read_file_media(MEDIA m, long long offset, uint32_t count, void *address);
128*48a628aeSchristos long write_file_media(MEDIA m, long long offset, uint32_t count, void *address);
1299428323dSchristos long close_file_media(MEDIA m);
1309428323dSchristos long os_reload_file_media(MEDIA m);
1319428323dSchristos FILE_MEDIA_ITERATOR new_file_iterator(void);
1329428323dSchristos void reset_file_iterator(MEDIA_ITERATOR m);
1339428323dSchristos char *step_file_iterator(MEDIA_ITERATOR m);
1349428323dSchristos void delete_file_iterator(MEDIA_ITERATOR m);
1359428323dSchristos 
1369428323dSchristos 
1379428323dSchristos /*
1389428323dSchristos  * Routines
1399428323dSchristos  */
1409428323dSchristos void
file_init(void)1419428323dSchristos file_init(void)
1429428323dSchristos {
1439428323dSchristos     if (file_inited != 0) {
1449428323dSchristos 	return;
1459428323dSchristos     }
1469428323dSchristos     file_inited = 1;
1479428323dSchristos 
1489428323dSchristos     file_info.kind = allocate_media_kind();
1499428323dSchristos }
1509428323dSchristos 
1519428323dSchristos 
1529428323dSchristos FILE_MEDIA
new_file_media(void)1539428323dSchristos new_file_media(void)
1549428323dSchristos {
1559428323dSchristos     return (FILE_MEDIA) new_media(sizeof(struct file_media));
1569428323dSchristos }
1579428323dSchristos 
1589428323dSchristos 
1599428323dSchristos int
compute_block_size(int fd)1609428323dSchristos compute_block_size(int fd)
1619428323dSchristos {
1629428323dSchristos     int size;
1639428323dSchristos     int max_size;
1649428323dSchristos     loff_t x;
1659428323dSchristos     long t;
1669428323dSchristos     int i;
1679428323dSchristos     char *buffer;
1689428323dSchristos 
1699428323dSchristos     max_size = 0;
1709428323dSchristos     for (i = 0; ; i++) {
1719428323dSchristos     	size = potential_block_sizes[i];
1729428323dSchristos     	if (size == 0) {
1739428323dSchristos 	    break;
1749428323dSchristos     	}
1759428323dSchristos     	if (max_size < size) {
1769428323dSchristos 	    max_size = size;
1779428323dSchristos     	}
1789428323dSchristos     }
1799428323dSchristos 
1809428323dSchristos     buffer = malloc(max_size);
1819428323dSchristos     if (buffer != 0) {
1829428323dSchristos 	for (i = 0; ; i++) {
1839428323dSchristos 	    size = potential_block_sizes[i];
1849428323dSchristos 	    if (size == 0) {
1859428323dSchristos 		break;
1869428323dSchristos 	    }
1879428323dSchristos 	    if ((x = llseek(fd, (loff_t)0, 0)) < 0) {
1889428323dSchristos 		error(errno, "Can't seek on file");
1899428323dSchristos 		break;
1909428323dSchristos 	    }
1919428323dSchristos 	    if ((t = read(fd, buffer, size)) == size) {
1929428323dSchristos 		free(buffer);
1939428323dSchristos 		return size;
1949428323dSchristos 	    }
1959428323dSchristos 	}
1969428323dSchristos     }
1979428323dSchristos     return 0;
1989428323dSchristos }
1999428323dSchristos 
2009428323dSchristos 
2019428323dSchristos MEDIA
open_file_as_media(char * file,int oflag)2029428323dSchristos open_file_as_media(char *file, int oflag)
2039428323dSchristos {
2049428323dSchristos     FILE_MEDIA	a;
2059428323dSchristos     int			fd;
2069428323dSchristos     loff_t off;
2079428323dSchristos #if defined(__linux__) || defined(__unix__)
2089428323dSchristos     struct stat info;
2099428323dSchristos #endif
2109428323dSchristos 
2119428323dSchristos     if (file_inited == 0) {
2129428323dSchristos 	    file_init();
2139428323dSchristos     }
2149428323dSchristos 
2159428323dSchristos     a = 0;
2169428323dSchristos     fd = open(file, oflag);
2179428323dSchristos     if (fd >= 0) {
2189428323dSchristos 	a = new_file_media();
2199428323dSchristos 	if (a != 0) {
2209428323dSchristos 	    a->m.kind = file_info.kind;
2219428323dSchristos 	    a->m.grain = compute_block_size(fd);
2229428323dSchristos 	    off = llseek(fd, (loff_t)0, 2);	/* seek to end of media */
2239428323dSchristos #if !defined(__linux__) && !defined(__unix__)
2249428323dSchristos 	    if (off <= 0) {
2259428323dSchristos 		off = 1; /* XXX not right? */
2269428323dSchristos 	    }
2279428323dSchristos #endif
2289428323dSchristos 	    //printf("file size = %Ld\n", off);
2299428323dSchristos 	    a->m.size_in_bytes = (long long) off;
2309428323dSchristos 	    a->m.do_read = read_file_media;
2319428323dSchristos 	    a->m.do_write = write_file_media;
2329428323dSchristos 	    a->m.do_close = close_file_media;
2339428323dSchristos 	    a->m.do_os_reload = os_reload_file_media;
2349428323dSchristos 	    a->fd = fd;
2359428323dSchristos 	    a->regular_file = 0;
2369428323dSchristos #if defined(__linux__) || defined(__unix__)
2379428323dSchristos 	    if (fstat(fd, &info) < 0) {
2389428323dSchristos 		error(errno, "can't stat file '%s'", file);
2399428323dSchristos 	    } else {
2409428323dSchristos 		a->regular_file = S_ISREG(info.st_mode);
2419428323dSchristos 	    }
2429428323dSchristos #endif
2439428323dSchristos 	} else {
2449428323dSchristos 	    close(fd);
2459428323dSchristos 	}
2469428323dSchristos     }
2479428323dSchristos     return (MEDIA) a;
2489428323dSchristos }
2499428323dSchristos 
2509428323dSchristos 
2519428323dSchristos long
read_file_media(MEDIA m,long long offset,uint32_t count,void * address)252*48a628aeSchristos read_file_media(MEDIA m, long long offset, uint32_t count, void *address)
2539428323dSchristos {
2549428323dSchristos     FILE_MEDIA a;
2559428323dSchristos     long rtn_value;
2569428323dSchristos     loff_t off;
2579428323dSchristos     int t;
2589428323dSchristos 
2599428323dSchristos     a = (FILE_MEDIA) m;
2609428323dSchristos     rtn_value = 0;
2619428323dSchristos     if (a == 0) {
2629428323dSchristos 	/* no media */
263*48a628aeSchristos 	fprintf(stderr,"no media\n");
2649428323dSchristos     } else if (a->m.kind != file_info.kind) {
2659428323dSchristos 	/* wrong kind - XXX need to error here - this is an internal problem */
266*48a628aeSchristos 	fprintf(stderr,"wrong kind\n");
2679428323dSchristos     } else if (count <= 0 || count % a->m.grain != 0) {
2689428323dSchristos 	/* can't handle size */
269*48a628aeSchristos 	fprintf(stderr,"bad size\n");
2709428323dSchristos     } else if (offset < 0 || offset % a->m.grain != 0) {
2719428323dSchristos 	/* can't handle offset */
272*48a628aeSchristos 	fprintf(stderr,"bad offset\n");
273*48a628aeSchristos     } else if (offset + (long long) count > a->m.size_in_bytes && a->m.size_in_bytes != (long long) 0) {
2749428323dSchristos 	/* check for offset (and offset+count) too large */
275*48a628aeSchristos 	fprintf(stderr,"offset+count too large\n");
2769428323dSchristos     } else if (offset + count > (long long) LOFF_MAX) {
2779428323dSchristos 	/* check for offset (and offset+count) too large */
278*48a628aeSchristos 	fprintf(stderr,"offset+count too large 2\n");
2799428323dSchristos     } else {
2809428323dSchristos 	/* do the read */
2819428323dSchristos 	off = offset;
2829428323dSchristos 	if ((off = llseek(a->fd, off, 0)) >= 0) {
283*48a628aeSchristos 	    if ((t = read(a->fd, address, count)) == (ssize_t)count) {
2849428323dSchristos 		rtn_value = 1;
2859428323dSchristos 	    } else {
286*48a628aeSchristos 		fprintf(stderr,"read failed\n");
2879428323dSchristos 	    }
2889428323dSchristos 	} else {
289*48a628aeSchristos 	    fprintf(stderr,"lseek failed\n");
2909428323dSchristos 	}
2919428323dSchristos     }
2929428323dSchristos     return rtn_value;
2939428323dSchristos }
2949428323dSchristos 
2959428323dSchristos 
2969428323dSchristos long
write_file_media(MEDIA m,long long offset,uint32_t count,void * address)297*48a628aeSchristos write_file_media(MEDIA m, long long offset, uint32_t count, void *address)
2989428323dSchristos {
2999428323dSchristos     FILE_MEDIA a;
3009428323dSchristos     long rtn_value;
3019428323dSchristos     loff_t off;
3029428323dSchristos     int t;
3039428323dSchristos 
3049428323dSchristos     a = (FILE_MEDIA) m;
3059428323dSchristos     rtn_value = 0;
3069428323dSchristos     if (a == 0) {
3079428323dSchristos 	/* no media */
3089428323dSchristos     } else if (a->m.kind != file_info.kind) {
3099428323dSchristos 	/* wrong kind - XXX need to error here - this is an internal problem */
3109428323dSchristos     } else if (count <= 0 || count % a->m.grain != 0) {
3119428323dSchristos 	/* can't handle size */
3129428323dSchristos     } else if (offset < 0 || offset % a->m.grain != 0) {
3139428323dSchristos 	/* can't handle offset */
3149428323dSchristos     } else if (offset + count > (long long) LOFF_MAX) {
3159428323dSchristos 	/* check for offset (and offset+count) too large */
3169428323dSchristos     } else {
3179428323dSchristos 	/* do the write  */
3189428323dSchristos 	off = offset;
3199428323dSchristos 	if ((off = llseek(a->fd, off, 0)) >= 0) {
320*48a628aeSchristos 		if ((t = write(a->fd, address, count)) == (ssize_t)count) {
321*48a628aeSchristos 		if (off + (long long) count > a->m.size_in_bytes) {
3229428323dSchristos 			a->m.size_in_bytes = off + count;
3239428323dSchristos 		}
3249428323dSchristos 		rtn_value = 1;
3259428323dSchristos 	    }
3269428323dSchristos 	}
3279428323dSchristos     }
3289428323dSchristos     return rtn_value;
3299428323dSchristos }
3309428323dSchristos 
3319428323dSchristos 
3329428323dSchristos long
close_file_media(MEDIA m)3339428323dSchristos close_file_media(MEDIA m)
3349428323dSchristos {
3359428323dSchristos     FILE_MEDIA a;
3369428323dSchristos 
3379428323dSchristos     a = (FILE_MEDIA) m;
3389428323dSchristos     if (a == 0) {
3399428323dSchristos 	return 0;
3409428323dSchristos     } else if (a->m.kind != file_info.kind) {
3419428323dSchristos 	/* XXX need to error here - this is an internal problem */
3429428323dSchristos 	return 0;
3439428323dSchristos     }
3449428323dSchristos 
3459428323dSchristos     close(a->fd);
3469428323dSchristos     return 1;
3479428323dSchristos }
3489428323dSchristos 
3499428323dSchristos 
3509428323dSchristos long
os_reload_file_media(MEDIA m)3519428323dSchristos os_reload_file_media(MEDIA m)
3529428323dSchristos {
3539428323dSchristos     FILE_MEDIA a;
3549428323dSchristos     long rtn_value;
3559428323dSchristos #if defined(__linux__)
3569428323dSchristos     int i;
3579428323dSchristos     int saved_errno;
3589428323dSchristos #endif
3599428323dSchristos 
3609428323dSchristos     a = (FILE_MEDIA) m;
3619428323dSchristos     rtn_value = 0;
3629428323dSchristos     if (a == 0) {
3639428323dSchristos 	/* no media */
3649428323dSchristos     } else if (a->m.kind != file_info.kind) {
3659428323dSchristos 	/* wrong kind - XXX need to error here - this is an internal problem */
3669428323dSchristos     } else if (a->regular_file) {
3679428323dSchristos 	/* okay - nothing to do */
3689428323dSchristos 	rtn_value = 1;
3699428323dSchristos     } else {
3709428323dSchristos #ifdef __linux__
3719428323dSchristos 	sync();
3729428323dSchristos 	sleep(2);
3739428323dSchristos 	if ((i = ioctl(a->fd, BLKRRPART)) != 0) {
3749428323dSchristos 	    saved_errno = errno;
3759428323dSchristos 	} else {
3769428323dSchristos 	    // some kernel versions (1.2.x) seem to have trouble
3779428323dSchristos 	    // rereading the partition table, but if asked to do it
3789428323dSchristos 	    // twice, the second time works. - biro@yggdrasil.com */
3799428323dSchristos 	    sync();
3809428323dSchristos 	    sleep(2);
3819428323dSchristos 	    if ((i = ioctl(a->fd, BLKRRPART)) != 0) {
3829428323dSchristos 		saved_errno = errno;
3839428323dSchristos 	    }
3849428323dSchristos 	}
3859428323dSchristos 
3869428323dSchristos 	// printf("Syncing disks.\n");
3879428323dSchristos 	sync();
3889428323dSchristos 	sleep(4);		/* for sync() */
3899428323dSchristos 
3909428323dSchristos 	if (i < 0) {
3919428323dSchristos 	    error(saved_errno, "Re-read of partition table failed");
3929428323dSchristos 	    printf("Reboot your system to ensure the "
3939428323dSchristos 		    "partition table is updated.\n");
3949428323dSchristos 	}
3959428323dSchristos #endif
3969428323dSchristos 	rtn_value = 1;
3979428323dSchristos     }
3989428323dSchristos     return rtn_value;
3999428323dSchristos }
4009428323dSchristos 
4019428323dSchristos 
4029428323dSchristos #if !defined(__linux__) && !defined(__unix__)
4039428323dSchristos #pragma mark -
4049428323dSchristos #endif
4059428323dSchristos 
4069428323dSchristos 
4079428323dSchristos FILE_MEDIA_ITERATOR
new_file_iterator(void)4089428323dSchristos new_file_iterator(void)
4099428323dSchristos {
4109428323dSchristos     return (FILE_MEDIA_ITERATOR) new_media_iterator(sizeof(struct file_media_iterator));
4119428323dSchristos }
4129428323dSchristos 
4139428323dSchristos 
4149428323dSchristos MEDIA_ITERATOR
create_file_iterator(void)4159428323dSchristos create_file_iterator(void)
4169428323dSchristos {
4179428323dSchristos     FILE_MEDIA_ITERATOR a;
4189428323dSchristos 
4199428323dSchristos     if (file_inited == 0) {
4209428323dSchristos 	file_init();
4219428323dSchristos     }
4229428323dSchristos 
4239428323dSchristos     a = new_file_iterator();
4249428323dSchristos     if (a != 0) {
4259428323dSchristos 	a->m.kind = file_info.kind;
4269428323dSchristos 	a->m.state = kInit;
4279428323dSchristos 	a->m.do_reset = reset_file_iterator;
4289428323dSchristos 	a->m.do_step = step_file_iterator;
4299428323dSchristos 	a->m.do_delete = delete_file_iterator;
4309428323dSchristos 	a->style = 0;
4319428323dSchristos 	a->index = 0;
4329428323dSchristos     }
4339428323dSchristos 
4349428323dSchristos     return (MEDIA_ITERATOR) a;
4359428323dSchristos }
4369428323dSchristos 
4379428323dSchristos 
4389428323dSchristos void
reset_file_iterator(MEDIA_ITERATOR m)4399428323dSchristos reset_file_iterator(MEDIA_ITERATOR m)
4409428323dSchristos {
4419428323dSchristos     FILE_MEDIA_ITERATOR a;
4429428323dSchristos 
4439428323dSchristos     a = (FILE_MEDIA_ITERATOR) m;
4449428323dSchristos     if (a == 0) {
4459428323dSchristos 	/* no media */
4469428323dSchristos     } else if (a->m.kind != file_info.kind) {
4479428323dSchristos 	/* wrong kind - XXX need to error here - this is an internal problem */
4489428323dSchristos     } else if (a->m.state != kInit) {
4499428323dSchristos 	a->m.state = kReset;
4509428323dSchristos     }
4519428323dSchristos }
4529428323dSchristos 
4539428323dSchristos 
4549428323dSchristos char *
step_file_iterator(MEDIA_ITERATOR m)4559428323dSchristos step_file_iterator(MEDIA_ITERATOR m)
4569428323dSchristos {
4579428323dSchristos     FILE_MEDIA_ITERATOR a;
4589428323dSchristos     char *result;
4599428323dSchristos     struct stat info;
4609428323dSchristos     int	fd;
4619428323dSchristos     int bump;
4629428323dSchristos     int value;
4639428323dSchristos 
4649428323dSchristos     a = (FILE_MEDIA_ITERATOR) m;
4659428323dSchristos     if (a == 0) {
4669428323dSchristos 	/* no media */
4679428323dSchristos     } else if (a->m.kind != file_info.kind) {
4689428323dSchristos 	/* wrong kind - XXX need to error here - this is an internal problem */
4699428323dSchristos     } else {
4709428323dSchristos 	switch (a->m.state) {
4719428323dSchristos 	case kInit:
4729428323dSchristos 	    a->m.state = kReset;
4739428323dSchristos 	    /* fall through to reset */
4749428323dSchristos 	case kReset:
4759428323dSchristos 	    a->style = 0 /* first style */;
4769428323dSchristos 	    a->index = 0 /* first index */;
4779428323dSchristos 	    a->m.state = kIterating;
4789428323dSchristos 	    /* fall through to iterate */
4799428323dSchristos 	case kIterating:
4809428323dSchristos 	    while (1) {
4819428323dSchristos 		if (a->style > kMaxStyle) {
4829428323dSchristos 		    break;
4839428323dSchristos 		}
4849428323dSchristos #ifndef notdef
4859428323dSchristos 		/* if old version of mklinux then skip CD drive */
4869428323dSchristos 		if (a->style == kSCSI_Disks && a->index == 3) {
4879428323dSchristos 		    a->index += 1;
4889428323dSchristos 		}
4899428323dSchristos #endif
4909428323dSchristos 		/* generate result */
4919428323dSchristos 		result = (char *) malloc(20);
4929428323dSchristos 		if (result != NULL) {
4939428323dSchristos 		    /*
4949428323dSchristos 		     * for DR3 we should actually iterate through:
4959428323dSchristos 		     *
4969428323dSchristos 		     *    /dev/sd[a...]    # first missing is end of list
4979428323dSchristos 		     *    /dev/hd[a...]    # may be holes in sequence
4989428323dSchristos 		     *    /dev/scd[0...]   # first missing is end of list
4999428323dSchristos 		     *
5009428323dSchristos 		     * and stop in each group when either a stat of
5019428323dSchristos 		     * the name fails or if an open fails for
5029428323dSchristos 		     * particular reasons.
5039428323dSchristos 		     */
5049428323dSchristos 		    bump = 0;
5059428323dSchristos 		    value = (int) a->index;
5069428323dSchristos 		    switch (a->style) {
5079428323dSchristos 		    case kSCSI_Disks:
5089428323dSchristos 			if (value < 26) {
509*48a628aeSchristos 			    snprintf(result, 20, "/dev/sd%c", 'a'+value);
5109428323dSchristos 			} else if (value < 676) {
511*48a628aeSchristos 			    snprintf(result, 20, "/dev/sd%c%c",
5129428323dSchristos 				    'a' + value / 26,
5139428323dSchristos 				    'a' + value % 26);
5149428323dSchristos 			} else {
5159428323dSchristos 			    bump = -1;
5169428323dSchristos 			}
5179428323dSchristos 			break;
5189428323dSchristos 		    case kATA_Devices:
5199428323dSchristos 			if (value < 26) {
520*48a628aeSchristos 			    snprintf(result, 20, "/dev/hd%c", 'a'+value);
5219428323dSchristos 			} else {
5229428323dSchristos 			    bump = -1;
5239428323dSchristos 			}
5249428323dSchristos 			break;
5259428323dSchristos 		    case kSCSI_CDs:
5269428323dSchristos 			if (value < 10) {
527*48a628aeSchristos 			    snprintf(result, 20, "/dev/scd%c", '0'+value);
5289428323dSchristos 			} else {
5299428323dSchristos 			    bump = -1;
5309428323dSchristos 			}
5319428323dSchristos 			break;
5329428323dSchristos 		    }
5339428323dSchristos 		    if (bump != 0) {
5349428323dSchristos 			// already set don't even check
5359428323dSchristos 		    } else if (stat(result, &info) < 0) {
5369428323dSchristos 			bump = 1;
5379428323dSchristos 		    } else if ((fd = open(result, O_RDONLY)) >= 0) {
5389428323dSchristos 			close(fd);
5399428323dSchristos #if defined(__linux__) || defined(__unix__)
5409428323dSchristos 		    } else if (errno == ENXIO || errno == ENODEV) {
5419428323dSchristos 			if (a->style == kATA_Devices) {
5429428323dSchristos 			    bump = -1;
5439428323dSchristos 			} else {
5449428323dSchristos 			    bump = 1;
5459428323dSchristos 			}
5469428323dSchristos #endif
5479428323dSchristos 		    }
5489428323dSchristos 		    if (bump) {
5499428323dSchristos 			if (bump > 0) {
5509428323dSchristos 			    a->style += 1; /* next style */
5519428323dSchristos 			    a->index = 0; /* first index again */
5529428323dSchristos 			} else {
5539428323dSchristos 			    a->index += 1; /* next index */
5549428323dSchristos 			}
5559428323dSchristos 			free(result);
5569428323dSchristos 			continue;
5579428323dSchristos 		    }
5589428323dSchristos 		}
5599428323dSchristos 
5609428323dSchristos 		a->index += 1; /* next index */
5619428323dSchristos 		return result;
5629428323dSchristos 	    }
5639428323dSchristos 	    a->m.state = kEnd;
5649428323dSchristos 	    /* fall through to end */
5659428323dSchristos 	case kEnd:
5669428323dSchristos 	default:
5679428323dSchristos 	    break;
5689428323dSchristos 	}
5699428323dSchristos     }
5709428323dSchristos     return 0 /* no entry */;
5719428323dSchristos }
5729428323dSchristos 
5739428323dSchristos 
5749428323dSchristos void
delete_file_iterator(MEDIA_ITERATOR m)5759428323dSchristos delete_file_iterator(MEDIA_ITERATOR m)
5769428323dSchristos {
5779428323dSchristos     return;
5789428323dSchristos }
579