zftape-eof.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * I use these routines just to decide when I have to fake a
  3. * volume-table to preserve compatibility to original ftape.
  4. */
  5. /*
  6. * Copyright (C) 1994-1995 Bas Laarhoven.
  7. *
  8. * Modified for zftape 1996, 1997 Claus Heine.
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2, or (at your option)
  12. any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program; see the file COPYING. If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20. * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.c,v $
  21. * $Revision: 1.2 $
  22. * $Date: 1997/10/05 19:19:02 $
  23. *
  24. * This file contains the eof mark handling code
  25. * for the QIC-40/80 floppy-tape driver for Linux.
  26. */
  27. #include <linux/string.h>
  28. #include <linux/errno.h>
  29. #include <linux/zftape.h>
  30. #include "../zftape/zftape-init.h"
  31. #include "../zftape/zftape-rw.h"
  32. #include "../zftape/zftape-eof.h"
  33. /* Global vars.
  34. */
  35. /* a copy of the failed sector log from the header segment.
  36. */
  37. eof_mark_union *zft_eof_map;
  38. /* number of eof marks (entries in bad sector log) on tape.
  39. */
  40. int zft_nr_eof_marks = -1;
  41. /* Local vars.
  42. */
  43. static char linux_tape_label[] = "Linux raw format V";
  44. enum {
  45. min_fmt_version = 1, max_fmt_version = 2
  46. };
  47. static unsigned ftape_fmt_version = 0;
  48. /* Ftape (mis)uses the bad sector log to record end-of-file marks.
  49. * Initially (when the tape is erased) all entries in the bad sector
  50. * log are added to the tape's bad sector map. The bad sector log then
  51. * is cleared.
  52. *
  53. * The bad sector log normally contains entries of the form:
  54. * even 16-bit word: segment number of bad sector
  55. * odd 16-bit word: encoded date
  56. * There can be a total of 448 entries (1792 bytes).
  57. *
  58. * My guess is that no program is using this bad sector log (the *
  59. * format seems useless as there is no indication of the bad sector
  60. * itself, only the segment) However, if any program does use the bad
  61. * sector log, the format used by ftape will let the program think
  62. * there are some bad sectors and no harm is done.
  63. *
  64. * The eof mark entries that ftape stores in the bad sector log: even
  65. * 16-bit word: segment number of eof mark odd 16-bit word: sector
  66. * number of eof mark [1..32]
  67. *
  68. * The zft_eof_map as maintained is a sorted list of eof mark entries.
  69. *
  70. *
  71. * The tape name field in the header segments is used to store a linux
  72. * tape identification string and a version number. This way the tape
  73. * can be recognized as a Linux raw format tape when using tools under
  74. * other OS's.
  75. *
  76. * 'Wide' QIC tapes (format code 4) don't have a failed sector list
  77. * anymore. That space is used for the (longer) bad sector map that
  78. * now is a variable length list too. We now store our end-of-file
  79. * marker list after the bad-sector-map on tape. The list is delimited
  80. * by a (__u32) 0 entry.
  81. */
  82. int zft_ftape_validate_label(char *label)
  83. {
  84. static char tmp_label[45];
  85. int result = 0;
  86. TRACE_FUN(ft_t_any);
  87. memcpy(tmp_label, label, FT_LABEL_SZ);
  88. tmp_label[FT_LABEL_SZ] = '\0';
  89. TRACE(ft_t_noise, "tape label = `%s'", tmp_label);
  90. ftape_fmt_version = 0;
  91. if (memcmp(label, linux_tape_label, strlen(linux_tape_label)) == 0) {
  92. int pos = strlen(linux_tape_label);
  93. while (label[pos] >= '0' && label[pos] <= '9') {
  94. ftape_fmt_version *= 10;
  95. ftape_fmt_version = label[ pos++] - '0';
  96. }
  97. result = (ftape_fmt_version >= min_fmt_version &&
  98. ftape_fmt_version <= max_fmt_version);
  99. }
  100. TRACE(ft_t_noise, "format version = %d", ftape_fmt_version);
  101. TRACE_EXIT result;
  102. }
  103. static __u8 * find_end_of_eof_list(__u8 * ptr, __u8 * limit)
  104. {
  105. while (ptr + 3 < limit) {
  106. if (get_unaligned((__u32*)ptr)) {
  107. ptr += sizeof(__u32);
  108. } else {
  109. return ptr;
  110. }
  111. }
  112. return NULL;
  113. }
  114. void zft_ftape_extract_file_marks(__u8* address)
  115. {
  116. int i;
  117. TRACE_FUN(ft_t_any);
  118. zft_eof_map = NULL;
  119. if (ft_format_code == fmt_var || ft_format_code == fmt_big) {
  120. __u8* end;
  121. __u8* start = ftape_find_end_of_bsm_list(address);
  122. zft_nr_eof_marks = 0;
  123. if (start) {
  124. start += 3; /* skip end of list mark */
  125. end = find_end_of_eof_list(start,
  126. address + FT_SEGMENT_SIZE);
  127. if (end && end - start <= FT_FSL_SIZE) {
  128. zft_nr_eof_marks = ((end - start) /
  129. sizeof(eof_mark_union));
  130. zft_eof_map = (eof_mark_union *)start;
  131. } else {
  132. TRACE(ft_t_err,
  133. "EOF Mark List is too long or damaged!");
  134. }
  135. } else {
  136. TRACE(ft_t_err,
  137. "Bad Sector List is too long or damaged !");
  138. }
  139. } else {
  140. zft_eof_map = (eof_mark_union *)&address[FT_FSL];
  141. zft_nr_eof_marks = GET2(address, FT_FSL_CNT);
  142. }
  143. TRACE(ft_t_noise, "number of file marks: %d", zft_nr_eof_marks);
  144. if (ftape_fmt_version == 1) {
  145. TRACE(ft_t_info, "swapping version 1 fields");
  146. /* version 1 format uses swapped sector and segment
  147. * fields, correct that !
  148. */
  149. for (i = 0; i < zft_nr_eof_marks; ++i) {
  150. __u16 tmp = GET2(&zft_eof_map[i].mark.segment,0);
  151. PUT2(&zft_eof_map[i].mark.segment, 0,
  152. GET2(&zft_eof_map[i].mark.date,0));
  153. PUT2(&zft_eof_map[i].mark.date, 0, tmp);
  154. }
  155. }
  156. for (i = 0; i < zft_nr_eof_marks; ++i) {
  157. TRACE(ft_t_noise, "eof mark: %5d/%2d",
  158. GET2(&zft_eof_map[i].mark.segment, 0),
  159. GET2(&zft_eof_map[i].mark.date,0));
  160. }
  161. TRACE_EXIT;
  162. }
  163. void zft_clear_ftape_file_marks(void)
  164. {
  165. TRACE_FUN(ft_t_flow);
  166. /* Clear failed sector log: remove all tape marks. We
  167. * don't use old ftape-style EOF-marks.
  168. */
  169. TRACE(ft_t_info, "Clearing old ftape's eof map");
  170. memset(zft_eof_map, 0, zft_nr_eof_marks * sizeof(__u32));
  171. zft_nr_eof_marks = 0;
  172. PUT2(zft_hseg_buf, FT_FSL_CNT, 0); /* nr of eof-marks */
  173. zft_header_changed = 1;
  174. zft_update_label(zft_hseg_buf);
  175. TRACE_EXIT;
  176. }