📄 dosread.c
字号:
do { disk_io(READ, clus_add(cl_no), buffer, cluster_size); rest = (entry->d_size > (long) cluster_size) ? cluster_size : (short) entry->d_size; if (Aflag) { for (i = 0; i < rest; i ++) { if (buffer [i] != '\r') putchar (buffer [i]); } if (ferror (stdout)) { fprintf (stderr, "%s: cannot write to stdout: %s\n", cmnd, strerror (errno)); exit (1); } } else { if (fwrite (buffer, 1, rest, stdout) != rest) { fprintf (stderr, "%s: cannot write to stdout: %s\n", cmnd, strerror (errno)); exit (1); } } entry->d_size -= (long) rest; cl_no = next_cluster(cl_no); if (cl_no == BAD16) { fflush (stdout); fprintf (stderr, "%s: reserved cluster value %x encountered.\n", cmnd, cl_no); exit (1); } } while (entry->d_size && cl_no != LAST_CLUSTER); if (cl_no != LAST_CLUSTER) fprintf (stderr, "%s: Too many clusters allocated for file.\n", cmnd); else if (entry->d_size != 0) fprintf (stderr, "%s: Premature EOF: %ld bytes left.\n", cmnd, entry->d_size);}/* Minimum of two long values */long lmin (a, b)long a, b;{ if (a < b) return a; else return b;}void make_file(dir_ptr, entries, name)DIRECTORY *dir_ptr;int entries;char *name;{ register DIRECTORY *entry = new_entry(dir_ptr, entries); register char *ptr; char buffer[MAX_CLUSTER_SIZE]; unsigned short cl_no = 0; int i, r; long size = 0L; unsigned short first_cluster, last_cluster; long chunk; memset (&entry->d_name[0], ' ', 11); /* clear entry */ for (i = 0, ptr = name; i < 8 && *ptr != '.' && *ptr; i++) entry->d_name[i] = *ptr++; while (*ptr != '.' && *ptr) ptr++; if (*ptr == '.') ptr++; for (i = 0; i < 3 && *ptr != '.' && *ptr; i++) entry->d_ext[i] = *ptr++; for (i = 0; i < 10; i++) entry->d_reserved[i] = '\0'; entry->d_attribute = '\0'; entry->d_cluster = 0; while (free_range (&first_cluster, &last_cluster)) { do { unsigned short nr_clus; chunk = lmin ((long) (last_cluster - first_cluster + 1) * cluster_size, (long) MAX_CLUSTER_SIZE); r = fill(buffer, chunk); if (r == 0) goto done; nr_clus = (r + cluster_size - 1) / cluster_size; disk_io(WRITE, clus_add(first_cluster), buffer, r); for (i = 0; i < nr_clus; i ++) { if (entry->d_cluster == 0) cl_no = entry->d_cluster = first_cluster; else { link_fat(cl_no, first_cluster); cl_no = first_cluster; } first_cluster ++; } size += r; } while (first_cluster <= last_cluster); } fprintf (stderr, "%s: disk full. File truncated\n", cmnd);done: if (entry->d_cluster != 0) link_fat(cl_no, LAST_CLUSTER); entry->d_size = size; fill_date(entry); disk_io(WRITE, mark, entry, DIR_SIZE); if (fat_dirty) flush_fat ();}#define SEC_MIN 60L#define SEC_HOUR (60L * SEC_MIN)#define SEC_DAY (24L * SEC_HOUR)#define SEC_YEAR (365L * SEC_DAY)#define SEC_LYEAR (366L * SEC_DAY)unsigned short mon_len[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};void fill_date(entry)DIRECTORY *entry;{ register long cur_time = time((long *) 0) - DOS_TIME; unsigned short year = 0, month = 1, day, hour, minutes, seconds; int i; long tmp; if (cur_time < 0) /* Date not set on booting ... */ cur_time = 0; for (;;) { tmp = (year % 4 == 0) ? SEC_LYEAR : SEC_YEAR; if (cur_time < tmp) break; cur_time -= tmp; year++; } day = (unsigned short) (cur_time / SEC_DAY); cur_time -= (long) day *SEC_DAY; hour = (unsigned short) (cur_time / SEC_HOUR); cur_time -= (long) hour *SEC_HOUR; minutes = (unsigned short) (cur_time / SEC_MIN); cur_time -= (long) minutes *SEC_MIN; seconds = (unsigned short) cur_time; mon_len[1] = (year % 4 == 0) ? 29 : 28; i = 0; while (day >= mon_len[i]) { month++; day -= mon_len[i++]; } day++; entry->d_date = (year << 9) | (month << 5) | day; entry->d_time = (hour << 11) | (minutes << 5) | seconds;}char *make_name(dir_ptr, dir_fl)register DIRECTORY *dir_ptr;short dir_fl;{ static char name_buf[14]; register char *ptr = name_buf; short i; for (i = 0; i < 8; i++) *ptr++ = dir_ptr->d_name[i]; while (*--ptr == ' '); assert (ptr >= name_buf); ptr++; if (dir_ptr->d_ext[0] != ' ') { *ptr++ = '.'; for (i = 0; i < 3; i++) *ptr++ = dir_ptr->d_ext[i]; while (*--ptr == ' '); ptr++; } if (dir_fl) *ptr++ = '/'; *ptr = '\0'; return name_buf;}int fill(buffer, size)register char *buffer;size_t size;{ static BOOL nl_mark = FALSE; char *last = &buffer[size]; char *begin = buffer; register int c; while (buffer < last) { if (nl_mark) { *buffer ++ = '\n'; nl_mark = FALSE; } else { c = getchar(); if (c == EOF) break; if (Aflag && c == '\n') { *buffer ++ = '\r'; nl_mark = TRUE; } else { *buffer++ = c; } } } return (buffer - begin);}#define HOUR 0xF800 /* Upper 5 bits */#define MIN 0x07E0 /* Middle 6 bits */#define YEAR 0xFE00 /* Upper 7 bits */#define MONTH 0x01E0 /* Mid 4 bits */#define DAY 0x01F /* Lowest 5 bits */char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};void xmodes(mode)int mode;{ printf ( "\t%c%c%c%c%c", (mode & SUB_DIR) ? 'd' : '-', (mode & 02) ? 'h' : '-', (mode & 04) ? 's' : '-', (mode & 01) ? '-' : 'w', (mode & 0x20) ? 'a' : '-');}void show(dir_ptr, name)DIRECTORY *dir_ptr;char *name;{ register unsigned short e_date = dir_ptr->d_date; register unsigned short e_time = dir_ptr->d_time; unsigned short next; char bname[20]; short i = 0; while (*name && *name != '/') bname[i++] = *name++; bname[i] = '\0'; if (!Lflag) { printf ( "%s\n", bname); return; } xmodes( (int) dir_ptr->d_attribute); printf ( "\t%s%s", bname, strlen(bname) < 8 ? "\t\t" : "\t"); i = 1; if (is_dir(dir_ptr)) { next = dir_ptr->d_cluster; while ((next = next_cluster(next)) != LAST_CLUSTER) i++; printf ("%8ld", (long) i * (long) cluster_size); } else printf ("%8ld", dir_ptr->d_size); printf (" %02d:%02d %2d %s %d\n", ((e_time & HOUR) >> 11), ((e_time & MIN) >> 5), (e_date & DAY), month[((e_date & MONTH) >> 5) - 1], ((e_date & YEAR) >> 9) + 1980);}void free_blocks(){ register unsigned short cl_no; long nr_free = 0; long nr_bad = 0; for (cl_no = 2; cl_no < total_clusters; cl_no++) { switch (next_cluster(cl_no)) { case FREE: nr_free++; break; case BAD16: nr_bad++; break; } } printf ("Free space: %ld bytes.\n", nr_free * (long) cluster_size); if (nr_bad != 0) printf ("Bad sectors: %ld bytes.\n", nr_bad * (long) cluster_size);}DIRECTORY *read_cluster(cluster)register unsigned int cluster;{ register DIRECTORY *sub_dir; if ((sub_dir = malloc(cluster_size)) == NULL) { fprintf (stderr, "%s: Cannot set break!\n", cmnd); exit(1); } disk_io(READ, clus_add(cluster), sub_dir, cluster_size); return sub_dir;}static unsigned short cl_index = 2;/* find a range of consecutive free clusters. Return TRUE if found * and return the first and last cluster in the |*first| and |*last|. * If no free clusters are left, return FALSE. * * Warning: Assumes that all of the range is used before the next call * to free_range or free_cluster. */BOOL free_range (first, last)unsigned short *first, *last;{ while (cl_index < total_clusters && next_cluster(cl_index) != FREE) cl_index++; if (cl_index >= total_clusters) return FALSE; *first = cl_index; while (cl_index < total_clusters && next_cluster(cl_index) == FREE) cl_index++; *last = cl_index - 1; return TRUE;}/* find a free cluster. * Return the number of the free cluster or a number > |total_clusters| * if none is found. * If |leave_fl| is TRUE, the the program will be terminated if * no free cluster can be found * * Warning: Assumes that the cluster is used before the next call * to free_range or free_cluster. */unsigned short free_cluster(leave_fl)BOOL leave_fl;{ while (cl_index < total_clusters && next_cluster(cl_index) != FREE) cl_index++; if (leave_fl && cl_index >= total_clusters) { fprintf (stderr, "%s: Diskette full. File not added.\n", cmnd); exit(1); } return cl_index++;}/* read a portion of the fat containing |cl_no| into the cache */void read_fat (cl_no) unsigned int cl_no;{ if (!cooked_fat) { /* Read the fat for the first time. We have to allocate all the * buffers */ if (fat_16) { /* FAT consists of little endian shorts. Easy to convert */ if ((cooked_fat = malloc (fat_size)) == NULL) { /* Oops, FAT doesn't fit into memory, just read * a chunk */ if ((cooked_fat = malloc (COOKED_SIZE)) == NULL) { fprintf (stderr, "%s: not enough memory for FAT cache. Use chmem\n", cmnd); exit (1); } cache_size = COOKED_SIZE / 2; } else { cache_size = fat_size / 2; } } else { /* 12 bit FAT. Difficult encoding, but small. Keep * both raw FAT and cooked version in memory. */ if ((cooked_fat = malloc (total_clusters * sizeof (short))) == NULL || (raw_fat = malloc (fat_size)) == NULL) { fprintf (stderr, "%s: not enough memory for FAT cache. Use chmem\n", cmnd); exit (1); } cache_size = total_clusters; } } fat_low = cl_no / cache_size * cache_size; fat_high = fat_low + cache_size - 1; if (!fat_16) { unsigned short *cp; unsigned char *rp; unsigned short i; disk_io (READ, FAT_START, raw_fat, fat_size); for (rp = raw_fat, cp = cooked_fat, i = 0; i < cache_size; rp += 3, i += 2) { *cp = *rp + ((*(rp + 1) & 0x0f) << 8); if (*cp == BAD) *cp = BAD16; else if (*cp == LAST_CLUSTER12) *cp = LAST_CLUSTER; cp ++; *cp = ((*(rp + 1) & 0xf0) >> 4) + (*(rp + 2) << 4); if (*cp == BAD) *cp = BAD16; else if (*cp == LAST_CLUSTER12) *cp = LAST_CLUSTER; cp ++; } } else { assert (sizeof (short) == 2); assert (CHAR_BIT == 8); /* just in case */ disk_io (READ, FAT_START + fat_low * 2, (void *)cooked_fat, cache_size * 2); if (big_endian) { unsigned short *cp; unsigned char *rp; unsigned short i; for (i = 0, rp = (unsigned char *)cooked_fat /* sic */, cp = cooked_fat; i < cache_size; rp += 2, cp ++, i ++) { *cp = c2u2 (rp); } } }}/* flush the fat cache out to disk */void flush_fat (){ if (fat_16) { if (big_endian) { unsigned short *cp; unsigned char *rp; unsigned short i; for (i = 0, rp = (unsigned char *)cooked_fat /* sic */, cp = cooked_fat; i < cache_size; rp += 2, cp ++, i ++) { *rp = *cp; *(rp + 1) = *cp >> 8; } } disk_io (WRITE, FAT_START + fat_low * 2, (void *)cooked_fat, cache_size * 2); disk_io (WRITE, FAT_START + fat_size + fat_low * 2, (void *)cooked_fat, cache_size * 2); } else { unsigned short *cp; unsigned char *rp; unsigned short i; for (rp = raw_fat, cp = cooked_fat, i = 0; i < cache_size; rp += 3, cp += 2, i += 2) { *rp = *cp; *(rp + 1) = ((*cp & 0xf00) >> 8) | ((*(cp + 1) & 0x00f) << 4); *(rp + 2) = ((*(cp + 1) & 0xff0) >> 4); } disk_io (WRITE, FAT_START, raw_fat, fat_size); disk_io (WRITE, FAT_START + fat_size, raw_fat, fat_size); }}/* make cl_2 the successor of cl_1 */void link_fat(cl_1, cl_2)unsigned int cl_1;unsigned int cl_2;{ if (cl_1 < fat_low || cl_1 > fat_high) { if (fat_dirty) flush_fat (); read_fat (cl_1); } cooked_fat [cl_1 - fat_low] = cl_2; fat_dirty = TRUE;}unsigned short next_cluster(cl_no)register unsigned int cl_no;{ if (cl_no < fat_low || cl_no > fat_high) { if (fat_dirty) flush_fat (); read_fat (cl_no); } return cooked_fat [cl_no - fat_low];}char *slash(str)register char *str;{ register char *result = str; while (*str) if (*str++ == '/') result = str; return result;}void add_path(file, slash_fl)char *file;BOOL slash_fl;{ register char *ptr = path; while (*ptr) ptr++; if (file == NIL_PTR) { if (ptr != path) ptr--; if (ptr != path) do { ptr--; } while (*ptr != '/' && ptr != path); if (ptr != path && !slash_fl) *ptr++ = '/'; *ptr = '\0'; } else strcpy (ptr, file);}void disk_io(op, seek, address, bytes)register BOOL op;unsigned long seek;void *address;register unsigned bytes;{ unsigned int r; if (lseek(disk, seek, SEEK_SET) < 0L) { fflush (stdout); fprintf (stderr, "%s: Bad lseek: %s\n", cmnd, strerror (errno)); exit(1); } if (op == READ) r = read(disk, (char *) address, bytes); else { r = write(disk, (char *) address, bytes); } if (r != bytes) { fprintf (stderr, "%s: read error: %s\n", cmnd, strerror (errno)); exit (1); }}char dosread_c_rcs_id [] = "$Id: dosread.c,v 1.8 1994/05/14 21:53:08 hjp Rel $";/* $Log: dosread.c,v $ * Revision 1.8 1994/05/14 21:53:08 hjp * filenames with more than 3 characters and extension work again. * removed debugging stuff and b_copy. * * Revision 1.7 1994/04/09 03:09:01 hjp * (posted to comp.os.minix) * merged branch 1.5.387 with stem. * changed treatment of drive parameter * * Revision 1.5.387.9 1994/04/09 02:07:51 hjp * Disk full no longer produces lost clusters but a truncated file. * Truncated file names to 8+3 before comparisons to avoid duplicate * files and filenames containing dots in the extension. * Replaced sbrk and brk by malloc and free (mixing brk and malloc causes * heap corruption which sometimes lead to core dumps. It may also have * been the cause of data corruption Kees reported). * Made global variables static and removed some unused ones. * Error messages now contain program name. * * Revision 1.5.387.8 1993/11/13 00:38:45 hjp * Posted to comp.os.minix and included in Minix-386vm 1.6.25.1. * Speed optimizations for 1.44 MB disks. * Replaced lowlevel I/O by stdio. * Simplified -a: Now only removes resp. adds CRs * Cleaned up. * * Revision 1.5.387.1 1993/01/15 19:32:29 ast * Released with 1.6.24b */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -