Home | History | Annotate | Line # | Download | only in dist
file_media.c revision 1.2
      1  1.1  christos /*
      2  1.1  christos  * file_media.c -
      3  1.1  christos  *
      4  1.1  christos  * Written by Eryk Vershen
      5  1.1  christos  */
      6  1.1  christos 
      7  1.1  christos /*
      8  1.1  christos  * Copyright 1997,1998 by Apple Computer, Inc.
      9  1.1  christos  *              All Rights Reserved
     10  1.1  christos  *
     11  1.1  christos  * Permission to use, copy, modify, and distribute this software and
     12  1.1  christos  * its documentation for any purpose and without fee is hereby granted,
     13  1.1  christos  * provided that the above copyright notice appears in all copies and
     14  1.1  christos  * that both the copyright notice and this permission notice appear in
     15  1.1  christos  * supporting documentation.
     16  1.1  christos  *
     17  1.1  christos  * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
     18  1.1  christos  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     19  1.1  christos  * FOR A PARTICULAR PURPOSE.
     20  1.1  christos  *
     21  1.1  christos  * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
     22  1.1  christos  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
     23  1.1  christos  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
     24  1.1  christos  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     25  1.1  christos  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     26  1.1  christos  */
     27  1.1  christos 
     28  1.1  christos // for printf()
     29  1.1  christos #include <stdio.h>
     30  1.1  christos // for malloc() & free()
     31  1.1  christos #include <stdlib.h>
     32  1.1  christos // for lseek(), read(), write(), close()
     33  1.1  christos #include <unistd.h>
     34  1.1  christos // for open()
     35  1.1  christos #include <fcntl.h>
     36  1.1  christos // for LONG_MAX
     37  1.1  christos #include <limits.h>
     38  1.1  christos // for errno
     39  1.1  christos #include <errno.h>
     40  1.1  christos 
     41  1.1  christos #ifdef __linux__
     42  1.1  christos #include <sys/ioctl.h>
     43  1.1  christos #include <linux/fs.h>
     44  1.1  christos #include <linux/hdreg.h>
     45  1.1  christos #include <sys/stat.h>
     46  1.1  christos #else
     47  1.1  christos #ifdef __unix__
     48  1.1  christos #include <sys/ioctl.h>
     49  1.1  christos #include <sys/stat.h>
     50  1.1  christos #endif
     51  1.1  christos #endif
     52  1.1  christos 
     53  1.1  christos #include "file_media.h"
     54  1.1  christos #include "errors.h"
     55  1.1  christos 
     56  1.1  christos 
     57  1.1  christos /*
     58  1.1  christos  * Defines
     59  1.1  christos  */
     60  1.1  christos #ifdef __linux__
     61  1.1  christos #define LOFF_MAX 9223372036854775807LL
     62  1.1  christos extern __loff_t llseek __P ((int __fd, __loff_t __offset, int __whence));
     63  1.2  christos #elif defined(__NetBSD__) || defined(__APPLE__)
     64  1.2  christos #define loff_t off_t
     65  1.2  christos #define llseek lseek
     66  1.2  christos #define LOFF_MAX LLONG_MAX
     67  1.1  christos #else
     68  1.1  christos #define loff_t long
     69  1.1  christos #define llseek lseek
     70  1.1  christos #define LOFF_MAX LONG_MAX
     71  1.1  christos #endif
     72  1.1  christos 
     73  1.1  christos 
     74  1.1  christos /*
     75  1.1  christos  * Types
     76  1.1  christos  */
     77  1.1  christos typedef struct file_media *FILE_MEDIA;
     78  1.1  christos 
     79  1.1  christos struct file_media {
     80  1.1  christos     struct media	m;
     81  1.1  christos     int			fd;
     82  1.1  christos     int			regular_file;
     83  1.1  christos };
     84  1.1  christos 
     85  1.1  christos struct file_media_globals {
     86  1.1  christos     long		exists;
     87  1.1  christos     long		kind;
     88  1.1  christos };
     89  1.1  christos 
     90  1.1  christos typedef struct file_media_iterator *FILE_MEDIA_ITERATOR;
     91  1.1  christos 
     92  1.1  christos struct file_media_iterator {
     93  1.1  christos     struct media_iterator   m;
     94  1.1  christos     long		    style;
     95  1.1  christos     long		    index;
     96  1.1  christos };
     97  1.1  christos 
     98  1.1  christos 
     99  1.1  christos /*
    100  1.1  christos  * Global Constants
    101  1.1  christos  */
    102  1.1  christos int potential_block_sizes[] = {
    103  1.2  christos     1, 512, 1024, 2048, 4096, 8192, 16834,
    104  1.1  christos     0
    105  1.1  christos };
    106  1.1  christos 
    107  1.1  christos enum {
    108  1.1  christos     kSCSI_Disks = 0,
    109  1.1  christos     kATA_Devices = 1,
    110  1.1  christos     kSCSI_CDs = 2,
    111  1.1  christos     kMaxStyle = 2
    112  1.1  christos };
    113  1.1  christos 
    114  1.1  christos 
    115  1.1  christos /*
    116  1.1  christos  * Global Variables
    117  1.1  christos  */
    118  1.1  christos static long file_inited = 0;
    119  1.1  christos static struct file_media_globals file_info;
    120  1.1  christos 
    121  1.1  christos /*
    122  1.1  christos  * Forward declarations
    123  1.1  christos  */
    124  1.1  christos int compute_block_size(int fd);
    125  1.1  christos void file_init(void);
    126  1.1  christos FILE_MEDIA new_file_media(void);
    127  1.2  christos long read_file_media(MEDIA m, long long offset, uint32_t count, void *address);
    128  1.2  christos long write_file_media(MEDIA m, long long offset, uint32_t count, void *address);
    129  1.1  christos long close_file_media(MEDIA m);
    130  1.1  christos long os_reload_file_media(MEDIA m);
    131  1.1  christos FILE_MEDIA_ITERATOR new_file_iterator(void);
    132  1.1  christos void reset_file_iterator(MEDIA_ITERATOR m);
    133  1.1  christos char *step_file_iterator(MEDIA_ITERATOR m);
    134  1.1  christos void delete_file_iterator(MEDIA_ITERATOR m);
    135  1.1  christos 
    136  1.1  christos 
    137  1.1  christos /*
    138  1.1  christos  * Routines
    139  1.1  christos  */
    140  1.1  christos void
    141  1.1  christos file_init(void)
    142  1.1  christos {
    143  1.1  christos     if (file_inited != 0) {
    144  1.1  christos 	return;
    145  1.1  christos     }
    146  1.1  christos     file_inited = 1;
    147  1.1  christos 
    148  1.1  christos     file_info.kind = allocate_media_kind();
    149  1.1  christos }
    150  1.1  christos 
    151  1.1  christos 
    152  1.1  christos FILE_MEDIA
    153  1.1  christos new_file_media(void)
    154  1.1  christos {
    155  1.1  christos     return (FILE_MEDIA) new_media(sizeof(struct file_media));
    156  1.1  christos }
    157  1.1  christos 
    158  1.1  christos 
    159  1.1  christos int
    160  1.1  christos compute_block_size(int fd)
    161  1.1  christos {
    162  1.1  christos     int size;
    163  1.1  christos     int max_size;
    164  1.1  christos     loff_t x;
    165  1.1  christos     long t;
    166  1.1  christos     int i;
    167  1.1  christos     char *buffer;
    168  1.1  christos 
    169  1.1  christos     max_size = 0;
    170  1.1  christos     for (i = 0; ; i++) {
    171  1.1  christos     	size = potential_block_sizes[i];
    172  1.1  christos     	if (size == 0) {
    173  1.1  christos 	    break;
    174  1.1  christos     	}
    175  1.1  christos     	if (max_size < size) {
    176  1.1  christos 	    max_size = size;
    177  1.1  christos     	}
    178  1.1  christos     }
    179  1.1  christos 
    180  1.1  christos     buffer = malloc(max_size);
    181  1.1  christos     if (buffer != 0) {
    182  1.1  christos 	for (i = 0; ; i++) {
    183  1.1  christos 	    size = potential_block_sizes[i];
    184  1.1  christos 	    if (size == 0) {
    185  1.1  christos 		break;
    186  1.1  christos 	    }
    187  1.1  christos 	    if ((x = llseek(fd, (loff_t)0, 0)) < 0) {
    188  1.1  christos 		error(errno, "Can't seek on file");
    189  1.1  christos 		break;
    190  1.1  christos 	    }
    191  1.1  christos 	    if ((t = read(fd, buffer, size)) == size) {
    192  1.1  christos 		free(buffer);
    193  1.1  christos 		return size;
    194  1.1  christos 	    }
    195  1.1  christos 	}
    196  1.1  christos     }
    197  1.1  christos     return 0;
    198  1.1  christos }
    199  1.1  christos 
    200  1.1  christos 
    201  1.1  christos MEDIA
    202  1.1  christos open_file_as_media(char *file, int oflag)
    203  1.1  christos {
    204  1.1  christos     FILE_MEDIA	a;
    205  1.1  christos     int			fd;
    206  1.1  christos     loff_t off;
    207  1.1  christos #if defined(__linux__) || defined(__unix__)
    208  1.1  christos     struct stat info;
    209  1.1  christos #endif
    210  1.1  christos 
    211  1.1  christos     if (file_inited == 0) {
    212  1.1  christos 	    file_init();
    213  1.1  christos     }
    214  1.1  christos 
    215  1.1  christos     a = 0;
    216  1.1  christos     fd = open(file, oflag);
    217  1.1  christos     if (fd >= 0) {
    218  1.1  christos 	a = new_file_media();
    219  1.1  christos 	if (a != 0) {
    220  1.1  christos 	    a->m.kind = file_info.kind;
    221  1.1  christos 	    a->m.grain = compute_block_size(fd);
    222  1.1  christos 	    off = llseek(fd, (loff_t)0, 2);	/* seek to end of media */
    223  1.1  christos #if !defined(__linux__) && !defined(__unix__)
    224  1.1  christos 	    if (off <= 0) {
    225  1.1  christos 		off = 1; /* XXX not right? */
    226  1.1  christos 	    }
    227  1.1  christos #endif
    228  1.1  christos 	    //printf("file size = %Ld\n", off);
    229  1.1  christos 	    a->m.size_in_bytes = (long long) off;
    230  1.1  christos 	    a->m.do_read = read_file_media;
    231  1.1  christos 	    a->m.do_write = write_file_media;
    232  1.1  christos 	    a->m.do_close = close_file_media;
    233  1.1  christos 	    a->m.do_os_reload = os_reload_file_media;
    234  1.1  christos 	    a->fd = fd;
    235  1.1  christos 	    a->regular_file = 0;
    236  1.1  christos #if defined(__linux__) || defined(__unix__)
    237  1.1  christos 	    if (fstat(fd, &info) < 0) {
    238  1.1  christos 		error(errno, "can't stat file '%s'", file);
    239  1.1  christos 	    } else {
    240  1.1  christos 		a->regular_file = S_ISREG(info.st_mode);
    241  1.1  christos 	    }
    242  1.1  christos #endif
    243  1.1  christos 	} else {
    244  1.1  christos 	    close(fd);
    245  1.1  christos 	}
    246  1.1  christos     }
    247  1.1  christos     return (MEDIA) a;
    248  1.1  christos }
    249  1.1  christos 
    250  1.1  christos 
    251  1.1  christos long
    252  1.2  christos read_file_media(MEDIA m, long long offset, uint32_t count, void *address)
    253  1.1  christos {
    254  1.1  christos     FILE_MEDIA a;
    255  1.1  christos     long rtn_value;
    256  1.1  christos     loff_t off;
    257  1.1  christos     int t;
    258  1.1  christos 
    259  1.1  christos     a = (FILE_MEDIA) m;
    260  1.1  christos     rtn_value = 0;
    261  1.1  christos     if (a == 0) {
    262  1.1  christos 	/* no media */
    263  1.2  christos 	fprintf(stderr,"no media\n");
    264  1.1  christos     } else if (a->m.kind != file_info.kind) {
    265  1.1  christos 	/* wrong kind - XXX need to error here - this is an internal problem */
    266  1.2  christos 	fprintf(stderr,"wrong kind\n");
    267  1.1  christos     } else if (count <= 0 || count % a->m.grain != 0) {
    268  1.1  christos 	/* can't handle size */
    269  1.2  christos 	fprintf(stderr,"bad size\n");
    270  1.1  christos     } else if (offset < 0 || offset % a->m.grain != 0) {
    271  1.1  christos 	/* can't handle offset */
    272  1.2  christos 	fprintf(stderr,"bad offset\n");
    273  1.2  christos     } else if (offset + (long long) count > a->m.size_in_bytes && a->m.size_in_bytes != (long long) 0) {
    274  1.1  christos 	/* check for offset (and offset+count) too large */
    275  1.2  christos 	fprintf(stderr,"offset+count too large\n");
    276  1.1  christos     } else if (offset + count > (long long) LOFF_MAX) {
    277  1.1  christos 	/* check for offset (and offset+count) too large */
    278  1.2  christos 	fprintf(stderr,"offset+count too large 2\n");
    279  1.1  christos     } else {
    280  1.1  christos 	/* do the read */
    281  1.1  christos 	off = offset;
    282  1.1  christos 	if ((off = llseek(a->fd, off, 0)) >= 0) {
    283  1.2  christos 	    if ((t = read(a->fd, address, count)) == (ssize_t)count) {
    284  1.1  christos 		rtn_value = 1;
    285  1.1  christos 	    } else {
    286  1.2  christos 		fprintf(stderr,"read failed\n");
    287  1.1  christos 	    }
    288  1.1  christos 	} else {
    289  1.2  christos 	    fprintf(stderr,"lseek failed\n");
    290  1.1  christos 	}
    291  1.1  christos     }
    292  1.1  christos     return rtn_value;
    293  1.1  christos }
    294  1.1  christos 
    295  1.1  christos 
    296  1.1  christos long
    297  1.2  christos write_file_media(MEDIA m, long long offset, uint32_t count, void *address)
    298  1.1  christos {
    299  1.1  christos     FILE_MEDIA a;
    300  1.1  christos     long rtn_value;
    301  1.1  christos     loff_t off;
    302  1.1  christos     int t;
    303  1.1  christos 
    304  1.1  christos     a = (FILE_MEDIA) m;
    305  1.1  christos     rtn_value = 0;
    306  1.1  christos     if (a == 0) {
    307  1.1  christos 	/* no media */
    308  1.1  christos     } else if (a->m.kind != file_info.kind) {
    309  1.1  christos 	/* wrong kind - XXX need to error here - this is an internal problem */
    310  1.1  christos     } else if (count <= 0 || count % a->m.grain != 0) {
    311  1.1  christos 	/* can't handle size */
    312  1.1  christos     } else if (offset < 0 || offset % a->m.grain != 0) {
    313  1.1  christos 	/* can't handle offset */
    314  1.1  christos     } else if (offset + count > (long long) LOFF_MAX) {
    315  1.1  christos 	/* check for offset (and offset+count) too large */
    316  1.1  christos     } else {
    317  1.1  christos 	/* do the write  */
    318  1.1  christos 	off = offset;
    319  1.1  christos 	if ((off = llseek(a->fd, off, 0)) >= 0) {
    320  1.2  christos 		if ((t = write(a->fd, address, count)) == (ssize_t)count) {
    321  1.2  christos 		if (off + (long long) count > a->m.size_in_bytes) {
    322  1.1  christos 			a->m.size_in_bytes = off + count;
    323  1.1  christos 		}
    324  1.1  christos 		rtn_value = 1;
    325  1.1  christos 	    }
    326  1.1  christos 	}
    327  1.1  christos     }
    328  1.1  christos     return rtn_value;
    329  1.1  christos }
    330  1.1  christos 
    331  1.1  christos 
    332  1.1  christos long
    333  1.1  christos close_file_media(MEDIA m)
    334  1.1  christos {
    335  1.1  christos     FILE_MEDIA a;
    336  1.1  christos 
    337  1.1  christos     a = (FILE_MEDIA) m;
    338  1.1  christos     if (a == 0) {
    339  1.1  christos 	return 0;
    340  1.1  christos     } else if (a->m.kind != file_info.kind) {
    341  1.1  christos 	/* XXX need to error here - this is an internal problem */
    342  1.1  christos 	return 0;
    343  1.1  christos     }
    344  1.1  christos 
    345  1.1  christos     close(a->fd);
    346  1.1  christos     return 1;
    347  1.1  christos }
    348  1.1  christos 
    349  1.1  christos 
    350  1.1  christos long
    351  1.1  christos os_reload_file_media(MEDIA m)
    352  1.1  christos {
    353  1.1  christos     FILE_MEDIA a;
    354  1.1  christos     long rtn_value;
    355  1.1  christos #if defined(__linux__)
    356  1.1  christos     int i;
    357  1.1  christos     int saved_errno;
    358  1.1  christos #endif
    359  1.1  christos 
    360  1.1  christos     a = (FILE_MEDIA) m;
    361  1.1  christos     rtn_value = 0;
    362  1.1  christos     if (a == 0) {
    363  1.1  christos 	/* no media */
    364  1.1  christos     } else if (a->m.kind != file_info.kind) {
    365  1.1  christos 	/* wrong kind - XXX need to error here - this is an internal problem */
    366  1.1  christos     } else if (a->regular_file) {
    367  1.1  christos 	/* okay - nothing to do */
    368  1.1  christos 	rtn_value = 1;
    369  1.1  christos     } else {
    370  1.1  christos #ifdef __linux__
    371  1.1  christos 	sync();
    372  1.1  christos 	sleep(2);
    373  1.1  christos 	if ((i = ioctl(a->fd, BLKRRPART)) != 0) {
    374  1.1  christos 	    saved_errno = errno;
    375  1.1  christos 	} else {
    376  1.1  christos 	    // some kernel versions (1.2.x) seem to have trouble
    377  1.1  christos 	    // rereading the partition table, but if asked to do it
    378  1.1  christos 	    // twice, the second time works. - biro (at) yggdrasil.com */
    379  1.1  christos 	    sync();
    380  1.1  christos 	    sleep(2);
    381  1.1  christos 	    if ((i = ioctl(a->fd, BLKRRPART)) != 0) {
    382  1.1  christos 		saved_errno = errno;
    383  1.1  christos 	    }
    384  1.1  christos 	}
    385  1.1  christos 
    386  1.1  christos 	// printf("Syncing disks.\n");
    387  1.1  christos 	sync();
    388  1.1  christos 	sleep(4);		/* for sync() */
    389  1.1  christos 
    390  1.1  christos 	if (i < 0) {
    391  1.1  christos 	    error(saved_errno, "Re-read of partition table failed");
    392  1.1  christos 	    printf("Reboot your system to ensure the "
    393  1.1  christos 		    "partition table is updated.\n");
    394  1.1  christos 	}
    395  1.1  christos #endif
    396  1.1  christos 	rtn_value = 1;
    397  1.1  christos     }
    398  1.1  christos     return rtn_value;
    399  1.1  christos }
    400  1.1  christos 
    401  1.1  christos 
    402  1.1  christos #if !defined(__linux__) && !defined(__unix__)
    403  1.1  christos #pragma mark -
    404  1.1  christos #endif
    405  1.1  christos 
    406  1.1  christos 
    407  1.1  christos FILE_MEDIA_ITERATOR
    408  1.1  christos new_file_iterator(void)
    409  1.1  christos {
    410  1.1  christos     return (FILE_MEDIA_ITERATOR) new_media_iterator(sizeof(struct file_media_iterator));
    411  1.1  christos }
    412  1.1  christos 
    413  1.1  christos 
    414  1.1  christos MEDIA_ITERATOR
    415  1.1  christos create_file_iterator(void)
    416  1.1  christos {
    417  1.1  christos     FILE_MEDIA_ITERATOR a;
    418  1.1  christos 
    419  1.1  christos     if (file_inited == 0) {
    420  1.1  christos 	file_init();
    421  1.1  christos     }
    422  1.1  christos 
    423  1.1  christos     a = new_file_iterator();
    424  1.1  christos     if (a != 0) {
    425  1.1  christos 	a->m.kind = file_info.kind;
    426  1.1  christos 	a->m.state = kInit;
    427  1.1  christos 	a->m.do_reset = reset_file_iterator;
    428  1.1  christos 	a->m.do_step = step_file_iterator;
    429  1.1  christos 	a->m.do_delete = delete_file_iterator;
    430  1.1  christos 	a->style = 0;
    431  1.1  christos 	a->index = 0;
    432  1.1  christos     }
    433  1.1  christos 
    434  1.1  christos     return (MEDIA_ITERATOR) a;
    435  1.1  christos }
    436  1.1  christos 
    437  1.1  christos 
    438  1.1  christos void
    439  1.1  christos reset_file_iterator(MEDIA_ITERATOR m)
    440  1.1  christos {
    441  1.1  christos     FILE_MEDIA_ITERATOR a;
    442  1.1  christos 
    443  1.1  christos     a = (FILE_MEDIA_ITERATOR) m;
    444  1.1  christos     if (a == 0) {
    445  1.1  christos 	/* no media */
    446  1.1  christos     } else if (a->m.kind != file_info.kind) {
    447  1.1  christos 	/* wrong kind - XXX need to error here - this is an internal problem */
    448  1.1  christos     } else if (a->m.state != kInit) {
    449  1.1  christos 	a->m.state = kReset;
    450  1.1  christos     }
    451  1.1  christos }
    452  1.1  christos 
    453  1.1  christos 
    454  1.1  christos char *
    455  1.1  christos step_file_iterator(MEDIA_ITERATOR m)
    456  1.1  christos {
    457  1.1  christos     FILE_MEDIA_ITERATOR a;
    458  1.1  christos     char *result;
    459  1.1  christos     struct stat info;
    460  1.1  christos     int	fd;
    461  1.1  christos     int bump;
    462  1.1  christos     int value;
    463  1.1  christos 
    464  1.1  christos     a = (FILE_MEDIA_ITERATOR) m;
    465  1.1  christos     if (a == 0) {
    466  1.1  christos 	/* no media */
    467  1.1  christos     } else if (a->m.kind != file_info.kind) {
    468  1.1  christos 	/* wrong kind - XXX need to error here - this is an internal problem */
    469  1.1  christos     } else {
    470  1.1  christos 	switch (a->m.state) {
    471  1.1  christos 	case kInit:
    472  1.1  christos 	    a->m.state = kReset;
    473  1.1  christos 	    /* fall through to reset */
    474  1.1  christos 	case kReset:
    475  1.1  christos 	    a->style = 0 /* first style */;
    476  1.1  christos 	    a->index = 0 /* first index */;
    477  1.1  christos 	    a->m.state = kIterating;
    478  1.1  christos 	    /* fall through to iterate */
    479  1.1  christos 	case kIterating:
    480  1.1  christos 	    while (1) {
    481  1.1  christos 		if (a->style > kMaxStyle) {
    482  1.1  christos 		    break;
    483  1.1  christos 		}
    484  1.1  christos #ifndef notdef
    485  1.1  christos 		/* if old version of mklinux then skip CD drive */
    486  1.1  christos 		if (a->style == kSCSI_Disks && a->index == 3) {
    487  1.1  christos 		    a->index += 1;
    488  1.1  christos 		}
    489  1.1  christos #endif
    490  1.1  christos 		/* generate result */
    491  1.1  christos 		result = (char *) malloc(20);
    492  1.1  christos 		if (result != NULL) {
    493  1.1  christos 		    /*
    494  1.1  christos 		     * for DR3 we should actually iterate through:
    495  1.1  christos 		     *
    496  1.1  christos 		     *    /dev/sd[a...]    # first missing is end of list
    497  1.1  christos 		     *    /dev/hd[a...]    # may be holes in sequence
    498  1.1  christos 		     *    /dev/scd[0...]   # first missing is end of list
    499  1.1  christos 		     *
    500  1.1  christos 		     * and stop in each group when either a stat of
    501  1.1  christos 		     * the name fails or if an open fails for
    502  1.1  christos 		     * particular reasons.
    503  1.1  christos 		     */
    504  1.1  christos 		    bump = 0;
    505  1.1  christos 		    value = (int) a->index;
    506  1.1  christos 		    switch (a->style) {
    507  1.1  christos 		    case kSCSI_Disks:
    508  1.1  christos 			if (value < 26) {
    509  1.2  christos 			    snprintf(result, 20, "/dev/sd%c", 'a'+value);
    510  1.1  christos 			} else if (value < 676) {
    511  1.2  christos 			    snprintf(result, 20, "/dev/sd%c%c",
    512  1.1  christos 				    'a' + value / 26,
    513  1.1  christos 				    'a' + value % 26);
    514  1.1  christos 			} else {
    515  1.1  christos 			    bump = -1;
    516  1.1  christos 			}
    517  1.1  christos 			break;
    518  1.1  christos 		    case kATA_Devices:
    519  1.1  christos 			if (value < 26) {
    520  1.2  christos 			    snprintf(result, 20, "/dev/hd%c", 'a'+value);
    521  1.1  christos 			} else {
    522  1.1  christos 			    bump = -1;
    523  1.1  christos 			}
    524  1.1  christos 			break;
    525  1.1  christos 		    case kSCSI_CDs:
    526  1.1  christos 			if (value < 10) {
    527  1.2  christos 			    snprintf(result, 20, "/dev/scd%c", '0'+value);
    528  1.1  christos 			} else {
    529  1.1  christos 			    bump = -1;
    530  1.1  christos 			}
    531  1.1  christos 			break;
    532  1.1  christos 		    }
    533  1.1  christos 		    if (bump != 0) {
    534  1.1  christos 			// already set don't even check
    535  1.1  christos 		    } else if (stat(result, &info) < 0) {
    536  1.1  christos 			bump = 1;
    537  1.1  christos 		    } else if ((fd = open(result, O_RDONLY)) >= 0) {
    538  1.1  christos 			close(fd);
    539  1.1  christos #if defined(__linux__) || defined(__unix__)
    540  1.1  christos 		    } else if (errno == ENXIO || errno == ENODEV) {
    541  1.1  christos 			if (a->style == kATA_Devices) {
    542  1.1  christos 			    bump = -1;
    543  1.1  christos 			} else {
    544  1.1  christos 			    bump = 1;
    545  1.1  christos 			}
    546  1.1  christos #endif
    547  1.1  christos 		    }
    548  1.1  christos 		    if (bump) {
    549  1.1  christos 			if (bump > 0) {
    550  1.1  christos 			    a->style += 1; /* next style */
    551  1.1  christos 			    a->index = 0; /* first index again */
    552  1.1  christos 			} else {
    553  1.1  christos 			    a->index += 1; /* next index */
    554  1.1  christos 			}
    555  1.1  christos 			free(result);
    556  1.1  christos 			continue;
    557  1.1  christos 		    }
    558  1.1  christos 		}
    559  1.1  christos 
    560  1.1  christos 		a->index += 1; /* next index */
    561  1.1  christos 		return result;
    562  1.1  christos 	    }
    563  1.1  christos 	    a->m.state = kEnd;
    564  1.1  christos 	    /* fall through to end */
    565  1.1  christos 	case kEnd:
    566  1.1  christos 	default:
    567  1.1  christos 	    break;
    568  1.1  christos 	}
    569  1.1  christos     }
    570  1.1  christos     return 0 /* no entry */;
    571  1.1  christos }
    572  1.1  christos 
    573  1.1  christos 
    574  1.1  christos void
    575  1.1  christos delete_file_iterator(MEDIA_ITERATOR m)
    576  1.1  christos {
    577  1.1  christos     return;
    578  1.1  christos }
    579