PageRenderTime 27ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/cmd/sort/common/check.c

https://bitbucket.org/a3217055/illumos-2
C | 225 lines | 141 code | 35 blank | 49 comment | 24 complexity | ca89974f18a20154cd2f57f3c66457c5 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, AGPL-3.0, BSD-3-Clause, LGPL-2.0, 0BSD, BSD-2-Clause, BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, GPL-2.0
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License, Version 1.0 only
  6. * (the "License"). You may not use this file except in compliance
  7. * with the License.
  8. *
  9. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10. * or http://www.opensolaris.org/os/licensing.
  11. * See the License for the specific language governing permissions
  12. * and limitations under the License.
  13. *
  14. * When distributing Covered Code, include this CDDL HEADER in each
  15. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16. * If applicable, add the following below this CDDL HEADER, with the
  17. * fields enclosed by brackets "[]" replaced with your own identifying
  18. * information: Portions Copyright [yyyy] [name of copyright owner]
  19. *
  20. * CDDL HEADER END
  21. */
  22. /*
  23. * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved.
  24. * Use is subject to license terms.
  25. */
  26. #pragma ident "%Z%%M% %I% %E% SMI"
  27. #include "check.h"
  28. #ifndef DEBUG
  29. #define MSG_DISORDER gettext("sort: disorder: ")
  30. #define MSG_NONUNIQUE gettext("sort: non-unique: ")
  31. #else /* DEBUG */
  32. #define MSG_DISORDER gettext("sort: disorder (%llu): ")
  33. #define MSG_NONUNIQUE gettext("sort: non-unique (%llu): ")
  34. #endif /* DEBUG */
  35. #define CHECK_FAILURE_DISORDER 0x1
  36. #define CHECK_FAILURE_NONUNIQUE 0x2
  37. #define CHECK_WIDE 0x4
  38. static void
  39. fail_check(line_rec_t *L, int flags, u_longlong_t lineno)
  40. {
  41. char *line;
  42. ssize_t length;
  43. if (flags & CHECK_WIDE) {
  44. if ((length = (ssize_t)wcstombs(NULL, L->l_data.wp, 0)) < 0)
  45. die(EMSG_ILLEGAL_CHAR);
  46. /*
  47. * +1 for null character
  48. */
  49. line = alloca(length + 1);
  50. (void) wcstombs(line, L->l_data.wp, L->l_data_length);
  51. line[length] = '\0';
  52. } else {
  53. line = L->l_data.sp;
  54. length = L->l_data_length;
  55. }
  56. if (flags & CHECK_FAILURE_DISORDER) {
  57. (void) fprintf(stderr, MSG_DISORDER, lineno);
  58. (void) write(fileno(stderr), line, length);
  59. (void) fprintf(stderr, "\n");
  60. return;
  61. }
  62. (void) fprintf(stderr, MSG_NONUNIQUE);
  63. (void) write(fileno(stderr), line, length);
  64. (void) fprintf(stderr, "\n");
  65. }
  66. static void
  67. swap_coll_bufs(line_rec_t *A, line_rec_t *B)
  68. {
  69. char *coll_buffer = B->l_collate.sp;
  70. ssize_t coll_bufsize = B->l_collate_bufsize;
  71. safe_free(B->l_raw_collate.sp);
  72. copy_line_rec(A, B);
  73. A->l_collate.sp = coll_buffer;
  74. A->l_collate_bufsize = coll_bufsize;
  75. A->l_raw_collate.sp = NULL;
  76. }
  77. /*
  78. * check_if_sorted() interacts with a stream in a slightly different way than a
  79. * simple sort or a merge operation: the check involves looking at two adjacent
  80. * lines of the file and verifying that they are collated according to the key
  81. * specifiers given. For files accessed via mmap(), this is simply done as the
  82. * entirety of the file is present in the address space. For files accessed via
  83. * stdio, regardless of locale, we must be able to guarantee that two lines are
  84. * present in memory at once. The basic buffer code for stdio does not make
  85. * such a guarantee, so we use stream_swap_buffer() to alternate between two
  86. * input buffers.
  87. */
  88. void
  89. check_if_sorted(sort_t *S)
  90. {
  91. size_t input_mem;
  92. int numerator, denominator;
  93. char *data_buffer = NULL;
  94. size_t data_bufsize = 0;
  95. line_rec_t last_line;
  96. u_longlong_t lineno = 0;
  97. int r;
  98. int swap_required;
  99. flag_t coll_flags;
  100. stream_t *cur_streamp = S->m_input_streams;
  101. ssize_t (*conversion_fcn)(field_t *, line_rec_t *, flag_t, vchar_t) =
  102. field_convert;
  103. int (*collation_fcn)(line_rec_t *, line_rec_t *, ssize_t, flag_t) =
  104. collated;
  105. set_memory_ratio(S, &numerator, &denominator);
  106. if (stream_open_for_read(S, cur_streamp) > 1)
  107. die(EMSG_CHECK);
  108. if (SOP_EOS(cur_streamp))
  109. exit(E_SUCCESS);
  110. (void) memset(&last_line, 0, sizeof (line_rec_t));
  111. /*
  112. * We need to swap data buffers for the stream with each fetch, except
  113. * on STREAM_MMAP (which are implicitly STREAM_SUSTAIN).
  114. */
  115. swap_required = !(cur_streamp->s_status & STREAM_MMAP);
  116. if (swap_required) {
  117. stream_set(cur_streamp, STREAM_INSTANT);
  118. /*
  119. * We use one half of the available memory for input, half for
  120. * each buffer. (The other half is left unreserved, in case
  121. * conversions to collatable form require it.)
  122. */
  123. input_mem = numerator * S->m_memory_available / denominator / 4;
  124. stream_set_size(cur_streamp, input_mem);
  125. stream_swap_buffer(cur_streamp, &data_buffer, &data_bufsize);
  126. stream_set_size(cur_streamp, input_mem);
  127. if (cur_streamp->s_status & STREAM_WIDE) {
  128. conversion_fcn = field_convert_wide;
  129. collation_fcn = collated_wide;
  130. }
  131. }
  132. if (SOP_PRIME(cur_streamp) > 1)
  133. die(EMSG_CHECK);
  134. if (S->m_field_options & FIELD_REVERSE_COMPARISONS)
  135. coll_flags = COLL_REVERSE;
  136. else
  137. coll_flags = 0;
  138. if (S->m_unique_lines)
  139. coll_flags |= COLL_UNIQUE;
  140. cur_streamp->s_current.l_collate_bufsize = INITIAL_COLLATION_SIZE
  141. * cur_streamp->s_element_size;
  142. cur_streamp->s_current.l_collate.sp = safe_realloc(NULL,
  143. cur_streamp->s_current.l_collate_bufsize);
  144. cur_streamp->s_current.l_raw_collate.sp = NULL;
  145. last_line.l_collate_bufsize = INITIAL_COLLATION_SIZE *
  146. cur_streamp->s_element_size;
  147. last_line.l_collate.sp = safe_realloc(NULL,
  148. last_line.l_collate_bufsize);
  149. last_line.l_raw_collate.sp = NULL;
  150. (void) conversion_fcn(S->m_fields_head, &cur_streamp->s_current,
  151. FCV_REALLOC, S->m_field_separator);
  152. swap_coll_bufs(&cur_streamp->s_current, &last_line);
  153. if (swap_required)
  154. stream_swap_buffer(cur_streamp, &data_buffer, &data_bufsize);
  155. while (!SOP_EOS(cur_streamp)) {
  156. (void) SOP_FETCH(cur_streamp);
  157. lineno++;
  158. (void) conversion_fcn(S->m_fields_head, &cur_streamp->s_current,
  159. FCV_REALLOC, S->m_field_separator);
  160. r = collation_fcn(&last_line, &cur_streamp->s_current, 0,
  161. coll_flags);
  162. if (r < 0 || (r == 0 && S->m_unique_lines == 0)) {
  163. swap_coll_bufs(&cur_streamp->s_current, &last_line);
  164. if (swap_required)
  165. stream_swap_buffer(cur_streamp, &data_buffer,
  166. &data_bufsize);
  167. continue;
  168. }
  169. if (r > 0) {
  170. #ifndef XPG4
  171. fail_check(&cur_streamp->s_current,
  172. CHECK_FAILURE_DISORDER |
  173. (S->m_single_byte_locale ? 0 : CHECK_WIDE),
  174. lineno);
  175. #endif /* XPG4 */
  176. exit(E_FAILED_CHECK);
  177. }
  178. if (r == 0 && S->m_unique_lines != 0) {
  179. #ifndef XPG4
  180. fail_check(&cur_streamp->s_current,
  181. CHECK_FAILURE_NONUNIQUE |
  182. (S->m_single_byte_locale ? 0 : CHECK_WIDE),
  183. lineno);
  184. #endif /* XPG4 */
  185. exit(E_FAILED_CHECK);
  186. }
  187. }
  188. exit(E_SUCCESS);
  189. /*NOTREACHED*/
  190. }