📄 disk_io.c
字号:
#else /* ! STAGE1_5 */ if (*filename == '(') { if ((filename = set_device (filename)) == 0) { current_drive = GRUB_INVALID_DRIVE; return 0; }# ifndef NO_BLOCK_FILES if (*filename != '/') open_partition (); else# endif /* ! NO_BLOCK_FILES */ open_device (); } else if (saved_drive != current_drive || saved_partition != current_partition || (*filename == '/' && fsys_type == NUM_FSYS) || buf_drive == -1) { current_drive = saved_drive; current_partition = saved_partition; /* allow for the error case of "no filesystem" after the partition is found. This makes block files work fine on no filesystem */# ifndef NO_BLOCK_FILES if (*filename != '/') open_partition (); else# endif /* ! NO_BLOCK_FILES */ open_device (); } #endif /* ! STAGE1_5 */ if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT)) return 0; else errnum = 0;#ifndef STAGE1_5 if (!sane_partition ()) return 0;#endif return filename;}#ifndef STAGE1_5/* * This prints the filesystem type or gives relevant information. */voidprint_fsys_type (void){ if (! do_completion) { printf (" Filesystem type "); if (fsys_type != NUM_FSYS) printf ("is %s, ", fsys_table[fsys_type].name); else printf ("unknown, "); if (current_partition == 0xFFFFFF) printf ("using whole disk\n"); else printf ("partition type 0x%x\n", current_slice & 0xFF); }}#endif /* STAGE1_5 */#ifndef STAGE1_5/* If DO_COMPLETION is true, just print NAME. Otherwise save the unique part into UNIQUE_STRING. */voidprint_a_completion (char *name){ /* If NAME is "." or "..", do not count it. */ if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0) return; if (do_completion) { char *buf = unique_string; if (! unique) while ((*buf++ = *name++)) ; else { while (*buf && (*buf == *name)) { buf++; name++; } /* mismatch, strip it. */ *buf = '\0'; } } else grub_printf (" %s", name); unique++;}/* * This lists the possible completions of a device string, filename, or * any sane combination of the two. */intprint_completions (int is_filename, int is_completion){ char *buf = (char *) COMPLETION_BUF; char *ptr = buf; unique_string = (char *) UNIQUE_BUF; *unique_string = 0; unique = 0; do_completion = is_completion; if (! is_filename) { /* Print the completions of builtin commands. */ struct builtin **builtin; if (! is_completion) grub_printf (" Possible commands are:"); for (builtin = builtin_table; (*builtin); builtin++) { /* If *BUILTIN cannot be run in the command-line, skip it. */ if (! ((*builtin)->flags & BUILTIN_CMDLINE)) continue; if (substring (buf, (*builtin)->name) <= 0) print_a_completion ((*builtin)->name); } if (is_completion && *unique_string) { if (unique == 1) { char *u = unique_string + grub_strlen (unique_string); *u++ = ' '; *u = 0; } grub_strcpy (buf, unique_string); } if (! is_completion) grub_putchar ('\n'); print_error (); do_completion = 0; if (errnum) return -1; else return unique - 1; } if (*buf == '/' || (ptr = set_device (buf)) || incomplete) { errnum = 0; if (*buf == '(' && (incomplete || ! *ptr)) { if (! part_choice) { /* disk completions */ int disk_no, i, j; struct geometry geom; if (! is_completion) grub_printf (" Possible disks are: "); if (!ptr || *(ptr-1) != 'd'#ifdef SUPPORT_NETBOOT || *(ptr-2) != 'n'#endif /* SUPPORT_NETBOOT */ || *(ptr-2) != 'c') { for (i = (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'h') ? 1:0); i < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2); i++) { for (j = 0; j < 8; j++) { disk_no = (i * 0x80) + j; if ((disk_choice || disk_no == current_drive) && ! get_diskinfo (disk_no, &geom)) { char dev_name[8]; grub_sprintf (dev_name, "%cd%d", i ? 'h':'f', j); print_a_completion (dev_name); } } } } if (cdrom_drive != GRUB_INVALID_DRIVE && (disk_choice || cdrom_drive == current_drive) && (!ptr || *(ptr-1) == '(' || (*(ptr-1) == 'd' && *(ptr-2) == 'c'))) print_a_completion ("cd");# ifdef SUPPORT_NETBOOT if (network_ready && (disk_choice || NETWORK_DRIVE == current_drive) && (!ptr || *(ptr-1) == '(' || (*(ptr-1) == 'd' && *(ptr-2) == 'n'))) print_a_completion ("nd");# endif /* SUPPORT_NETBOOT */ if (is_completion && *unique_string) { ptr = buf; while (*ptr != '(') ptr--; ptr++; grub_strcpy (ptr, unique_string); if (unique == 1) { ptr += grub_strlen (ptr); if (*unique_string == 'h') { *ptr++ = ','; *ptr = 0; } else { *ptr++ = ')'; *ptr = 0; } } } if (! is_completion) grub_putchar ('\n'); } else { /* partition completions */ if (part_choice == PART_CHOSEN && open_partition () && ! IS_PC_SLICE_TYPE_BSD (current_slice)) { unique = 1; ptr = buf + grub_strlen (buf); if (*(ptr - 1) != ')') { *ptr++ = ')'; *ptr = 0; } } else { if (! is_completion) grub_printf (" Possible partitions are:\n"); real_open_partition (1); if (is_completion && *unique_string) { ptr = buf; while (*ptr++ != ',') ; grub_strcpy (ptr, unique_string); } } } } else if (ptr && *ptr == '/') { /* filename completions */ if (! is_completion) grub_printf (" Possible files are:"); dir (buf); if (is_completion && *unique_string) { ptr += grub_strlen (ptr); while (*ptr != '/') ptr--; ptr++; grub_strcpy (ptr, unique_string); if (unique == 1) { ptr += grub_strlen (unique_string); /* Check if the file UNIQUE_STRING is a directory. */ *ptr = '/'; *(ptr + 1) = 0; dir (buf); /* Restore the original unique value. */ unique = 1; if (errnum) { /* Regular file */ errnum = 0; *ptr = ' '; *(ptr + 1) = 0; } } } if (! is_completion) grub_putchar ('\n'); } else errnum = ERR_BAD_FILENAME; } print_error (); do_completion = 0; if (errnum) return -1; else return unique - 1;}#endif /* STAGE1_5 *//* * This is the generic file open function. */intgrub_open (char *filename){#ifndef NO_DECOMPRESSION compressed_file = 0;#endif /* NO_DECOMPRESSION */ /* if any "dir" function uses/sets filepos, it must set it to zero before returning if opening a file! */ filepos = 0; if (!(filename = setup_part (filename))) return 0;#ifndef NO_BLOCK_FILES block_file = 0;#endif /* NO_BLOCK_FILES */ /* This accounts for partial filesystem implementations. */ fsmax = MAXINT; if (*filename != '/') {#ifndef NO_BLOCK_FILES char *ptr = filename; int tmp, list_addr = BLK_BLKLIST_START; filemax = 0; while (list_addr < BLK_MAX_ADDR) { tmp = 0; safe_parse_maxint (&ptr, &tmp); errnum = 0; if (*ptr != '+') { if ((*ptr && *ptr != '/' && !isspace (*ptr)) || tmp == 0 || tmp > filemax) errnum = ERR_BAD_FILENAME; else filemax = tmp; break; } /* since we use the same filesystem buffer, mark it to be remounted */ fsys_type = NUM_FSYS; BLK_BLKSTART (list_addr) = tmp; ptr++; if (!safe_parse_maxint (&ptr, &tmp) || tmp == 0 || (*ptr && *ptr != ',' && *ptr != '/' && !isspace (*ptr))) { errnum = ERR_BAD_FILENAME; break; } BLK_BLKLENGTH (list_addr) = tmp; filemax += (tmp * SECTOR_SIZE); list_addr += BLK_BLKLIST_INC_VAL; if (*ptr != ',') break; ptr++; } if (list_addr < BLK_MAX_ADDR && ptr != filename && !errnum) { block_file = 1; BLK_CUR_FILEPOS = 0; BLK_CUR_BLKLIST = BLK_BLKLIST_START; BLK_CUR_BLKNUM = 0;#ifndef NO_DECOMPRESSION return gunzip_test_header ();#else /* NO_DECOMPRESSION */ return 1;#endif /* NO_DECOMPRESSION */ }#else /* NO_BLOCK_FILES */ errnum = ERR_BAD_FILENAME;#endif /* NO_BLOCK_FILES */ } if (!errnum && fsys_type == NUM_FSYS) errnum = ERR_FSYS_MOUNT;# ifndef STAGE1_5 /* set "dir" function to open a file */ print_possibilities = 0;# endif if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename)) {#ifndef NO_DECOMPRESSION return gunzip_test_header ();#else /* NO_DECOMPRESSION */ return 1;#endif /* NO_DECOMPRESSION */ } return 0;}intgrub_read (char *buf, int len){ /* Make sure "filepos" is a sane value */ if ((filepos < 0) || (filepos > filemax)) filepos = filemax; /* Make sure "len" is a sane value */ if ((len < 0) || (len > (filemax - filepos))) len = filemax - filepos; /* if target file position is past the end of the supported/configured filesize, then there is an error */ if (filepos + len > fsmax) { errnum = ERR_FILELENGTH; return 0; }#ifndef NO_DECOMPRESSION if (compressed_file) return gunzip_read (buf, len);#endif /* NO_DECOMPRESSION */#ifndef NO_BLOCK_FILES if (block_file) { int size, off, ret = 0; while (len && !errnum) { /* we may need to look for the right block in the list(s) */ if (filepos < BLK_CUR_FILEPOS) { BLK_CUR_FILEPOS = 0; BLK_CUR_BLKLIST = BLK_BLKLIST_START; BLK_CUR_BLKNUM = 0; } /* run BLK_CUR_FILEPOS up to filepos */ while (filepos > BLK_CUR_FILEPOS) { if ((filepos - (BLK_CUR_FILEPOS & ~(SECTOR_SIZE - 1))) >= SECTOR_SIZE) { BLK_CUR_FILEPOS += SECTOR_SIZE; BLK_CUR_BLKNUM++; if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST)) { BLK_CUR_BLKLIST += BLK_BLKLIST_INC_VAL; BLK_CUR_BLKNUM = 0; } } else BLK_CUR_FILEPOS = filepos; } off = filepos & (SECTOR_SIZE - 1); size = ((BLK_BLKLENGTH (BLK_CUR_BLKLIST) - BLK_CUR_BLKNUM) * SECTOR_SIZE) - off; if (size > len) size = len; disk_read_func = disk_read_hook; /* read current block and put it in the right place in memory */ devread (BLK_BLKSTART (BLK_CUR_BLKLIST) + BLK_CUR_BLKNUM, off, size, buf); disk_read_func = NULL; len -= size; filepos += size; ret += size; buf += size; } if (errnum) ret = 0; return ret; }#endif /* NO_BLOCK_FILES */ if (fsys_type == NUM_FSYS) { errnum = ERR_FSYS_MOUNT; return 0; } return (*(fsys_table[fsys_type].read_func)) (buf, len);}#ifndef STAGE1_5/* Reposition a file offset. */intgrub_seek (int offset){ if (offset > filemax || offset < 0) return -1; filepos = offset; return offset;}intdir (char *dirname){#ifndef NO_DECOMPRESSION compressed_file = 0;#endif /* NO_DECOMPRESSION */ if (!(dirname = setup_part (dirname))) return 0; if (*dirname != '/') errnum = ERR_BAD_FILENAME; if (fsys_type == NUM_FSYS) errnum = ERR_FSYS_MOUNT; if (errnum) return 0; /* set "dir" function to list completions */ print_possibilities = 1; return (*(fsys_table[fsys_type].dir_func)) (dirname);}#endif /* STAGE1_5 */void grub_close (void){#ifndef NO_BLOCK_FILES if (block_file) return;#endif /* NO_BLOCK_FILES */ if (fsys_table[fsys_type].close_func != 0) (*(fsys_table[fsys_type].close_func)) ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -