1 /*
2 * Copyright (c) 1993 Atsushi Murai (amurai@spec.co.jp)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * 4. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY Atsushi Murai(amurai@spec.co.jp)``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $Id: $
32 */
33
34 #include "sys/param.h"
35 #include "sys/file.h"
36 #include "sys/mount.h"
37 #include "sys/time.h"
38 #include "sys/errno.h"
39 #include "uio.h"
40 #include "buf.h"
41 #include "kernel.h"
42
43 #include "vnode.h"
44 #include "iso.h"
45 #include "isofs_node.h"
46 #include "isofs_rrip.h"
47 #include "iso_rrip.h"
48
49 #include "prototypes.h"
50
51 /*
52 * POSIX file attribute
53 */
isofs_rrip_attr(p,ana)54 static int isofs_rrip_attr( p, ana )
55 ISO_RRIP_ATTR *p;
56 ISO_RRIP_ANALYZE *ana;
57 {
58 ana->inode.iso_mode = isonum_731(p->mode_l);
59 ana->inode.iso_uid = (uid_t)isonum_731(p->uid_l);
60 ana->inode.iso_gid = (gid_t)isonum_731(p->gid_l);
61 ana->inode.iso_links = isonum_731(p->links_l);
62 return;
63 }
64
isofs_rrip_defattr(isodir,ana)65 int isofs_rrip_defattr( isodir, ana )
66 struct iso_directory_record *isodir;
67 ISO_RRIP_ANALYZE *ana;
68 {
69 ana->inode.iso_mode = (VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6);
70 ana->inode.iso_uid = (uid_t)0;
71 ana->inode.iso_gid = (gid_t)0;
72 }
73
74 /*
75 * POSIX device modes
76 */
isofs_rrip_device(p,ana)77 static int isofs_rrip_device( p, ana )
78 ISO_RRIP_DEVICE *p;
79 ISO_RRIP_ANALYZE *ana;
80 {
81 char buf[3];
82
83 buf[0] = p->h.type[0];
84 buf[1] = p->h.type[1];
85 buf[2] = 0x00;
86
87 /* printf("isofs:%s[%d] high=0x%08x, low=0x%08x\n",
88 buf,
89 isonum_711(p->h.length),
90 isonum_731(p->dev_t_high_l),
91 isonum_731(p->dev_t_low_l)
92 ); */
93 ana->inode.iso_dev = makedev(isonum_731(p->dev_t_high_l),
94 isonum_731(p->dev_t_low_l));
95 return;
96 }
97
98 /*
99 * Symbolic Links
100 */
isofs_rrip_slink(p,ana)101 static int isofs_rrip_slink( p, ana )
102 ISO_RRIP_SLINK *p;
103 ISO_RRIP_ANALYZE *ana;
104 {
105 return;
106 }
107
108 /*
109 * Alternate name
110 */
isofs_rrip_altname(p,ana)111 static int isofs_rrip_altname( p, ana )
112 ISO_RRIP_ALTNAME *p;
113 ISO_RRIP_ANALYZE *ana;
114 {
115 return;
116 }
117
118 /*
119 * Child Link
120 */
isofs_rrip_clink(p,ana)121 static int isofs_rrip_clink( p, ana )
122 ISO_RRIP_CLINK *p;
123 ISO_RRIP_ANALYZE *ana;
124 {
125 char buf[3];
126 buf[0] = p->h.type[0];
127 buf[1] = p->h.type[1];
128 buf[2] = 0x00;
129 printf("isofs:%s[%d] loc=%d\n",
130 buf,
131 isonum_711(p->h.length),
132 isonum_733(p->dir_loc)
133 );
134 ana->inode.iso_cln = isonum_733(p->dir_loc);
135 return;
136 }
137
138 /*
139 * Parent Link
140 */
isofs_rrip_plink(p,ana)141 static int isofs_rrip_plink( p, ana )
142 ISO_RRIP_PLINK *p;
143 ISO_RRIP_ANALYZE *ana;
144 {
145
146 char buf[3];
147 buf[0] = p->h.type[0];
148 buf[1] = p->h.type[1];
149 buf[2] = 0x00;
150 printf("isofs:%s[%d] loc=%d\n",
151 buf,
152 isonum_711(p->h.length),
153 isonum_733(p->dir_loc)
154 );
155 ana->inode.iso_pln = isonum_733(p->dir_loc);
156 return;
157 }
158
159 /*
160 * Relocated directory
161 */
isofs_rrip_reldir(p,ana)162 static int isofs_rrip_reldir( p, ana )
163 ISO_RRIP_RELDIR *p;
164 ISO_RRIP_ANALYZE *ana;
165 {
166 char buf[3];
167
168 buf[0] = p->h.type[0];
169 buf[1] = p->h.type[1];
170 buf[2] = 0x00;
171
172 printf("isofs:%s[%d]\n",buf, isonum_711(p->h.length) );
173 return;
174 }
175
176 /*
177 * Time stamp
178 */
isofs_rrip_tstamp_conv7(pi,pu)179 static void isofs_rrip_tstamp_conv7(pi, pu)
180 char *pi;
181 struct timeval *pu;
182 {
183 int i;
184 int crtime,days;
185 int year,month,day,hour,minute,second,tz;
186
187 year = pi[0] - 70;
188 month = pi[1];
189 day = pi[2];
190 hour = pi[3];
191 minute = pi[4];
192 second = pi[5];
193 tz = pi[6];
194
195 if (year < 0) {
196 crtime = 0;
197 } else {
198 int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
199 days = year * 365;
200 if (year > 2)
201 days += (year+2) / 4;
202 for (i = 1; i < month; i++)
203 days += monlen[i-1];
204 if (((year+2) % 4) == 0 && month > 2)
205 days++;
206 days += day - 1;
207 crtime = ((((days * 24) + hour) * 60 + minute) * 60)
208 + second;
209
210 /* sign extend */
211 if (tz & 0x80)
212 tz |= (-1 << 8);
213
214 /* timezone offset is unreliable on some disks */
215 if (-48 <= tz && tz <= 52)
216 crtime += tz * 15 * 60;
217 }
218 pu->tv_sec = crtime;
219 pu->tv_usec = 0;
220 }
221
222
isofs_chars2ui(begin,end)223 static unsigned isofs_chars2ui( begin, end )
224 unsigned char *begin;
225 unsigned char *end;
226 {
227 unsigned rc=0;
228 int len;
229 int wlen;
230 static int pow[]={ 1, 10, 100, 1000 };
231
232 len = end - begin;
233 wlen= len;
234 for (; len >= 0; len -- ) {
235 rc += ( *(begin+len) * pow[wlen - len] );
236 }
237 return( rc );
238 }
239
isofs_rrip_tstamp_conv17(pi,pu)240 static void isofs_rrip_tstamp_conv17(pi, pu)
241 unsigned char *pi;
242 struct timeval *pu;
243 {
244 unsigned char buf[7];
245
246 /* year:"0001"-"9999" -> -1900 */
247 buf[0] = (unsigned char)(isofs_chars2ui( &pi[0], &pi[3]) - 1900 );
248
249 /* month: " 1"-"12" -> 1 - 12 */
250 buf[1] = (unsigned char)isofs_chars2ui( &pi[4], &pi[5]);
251
252 /* day: " 1"-"31" -> 1 - 31 */
253 buf[2] = isofs_chars2ui( &pi[6], &pi[7]);
254
255 /* hour: " 0"-"23" -> 0 - 23 */
256 buf[3] = isofs_chars2ui( &pi[8], &pi[9]);
257
258 /* minute:" 0"-"59" -> 0 - 59 */
259 buf[4] = isofs_chars2ui( &pi[10], &pi[11] );
260
261 /* second:" 0"-"59" -> 0 - 59 */
262 buf[5] = isofs_chars2ui( &pi[12], &pi[13] );
263
264 /* difference of GMT */
265 buf[6] = pi[16];
266
267 isofs_rrip_tstamp_conv7(buf, pu);
268 }
269
isofs_rrip_tstamp(p,ana)270 static int isofs_rrip_tstamp( p, ana )
271 ISO_RRIP_TSTAMP *p;
272 ISO_RRIP_ANALYZE *ana;
273 {
274 unsigned char *ptime;
275
276 ptime = p->time;
277
278 /* Check a format of time stamp (7bytes/17bytes) */
279 if ( !(*p->flags & ISO_SUSP_TSTAMP_FORM17 ) ) {
280 isofs_rrip_tstamp_conv7(ptime, &ana->inode.iso_ctime );
281
282 if ( *p->flags & ISO_SUSP_TSTAMP_MODIFY )
283 isofs_rrip_tstamp_conv7(ptime+7, &ana->inode.iso_mtime );
284 else
285 ana->inode.iso_mtime = ana->inode.iso_ctime;
286
287 if ( *p->flags & ISO_SUSP_TSTAMP_ACCESS )
288 isofs_rrip_tstamp_conv7(ptime+14, &ana->inode.iso_atime );
289 else
290 ana->inode.iso_atime = ana->inode.iso_ctime;
291 } else {
292 isofs_rrip_tstamp_conv17(ptime, &ana->inode.iso_ctime );
293
294 if ( *p->flags & ISO_SUSP_TSTAMP_MODIFY )
295 isofs_rrip_tstamp_conv17(ptime+17, &ana->inode.iso_mtime );
296 else
297 ana->inode.iso_mtime = ana->inode.iso_ctime;
298
299 if ( *p->flags & ISO_SUSP_TSTAMP_ACCESS )
300 isofs_rrip_tstamp_conv17(ptime+34, &ana->inode.iso_atime );
301 else
302 ana->inode.iso_atime = ana->inode.iso_ctime;
303 }
304 return;
305 }
306
isofs_rrip_deftstamp(isodir,ana)307 int isofs_rrip_deftstamp( isodir, ana )
308 struct iso_directory_record *isodir;
309 ISO_RRIP_ANALYZE *ana;
310 {
311 isofs_rrip_tstamp_conv7(isodir->date, &ana->inode.iso_ctime );
312 ana->inode.iso_atime = ana->inode.iso_ctime;
313 ana->inode.iso_mtime = ana->inode.iso_ctime;
314 }
315
316
317 /*
318 * Flag indicating
319 * Nothing to do....
320 */
isofs_rrip_idflag(p,ana)321 static int isofs_rrip_idflag( p, ana )
322 ISO_RRIP_IDFLAG *p;
323 ISO_RRIP_ANALYZE *ana;
324 {
325 char buf[3];
326
327 buf[0] = p->h.type[0];
328 buf[1] = p->h.type[1];
329 buf[2] = 0x00;
330
331 printf("isofs:%s[%d] idflag=0x%x\n",
332 buf,
333 isonum_711(p->h.length),
334 p->flags );
335 return;
336 }
337
338 /*
339 * Extension reference
340 * Nothing to do....
341 */
isofs_rrip_exflag(p,ana)342 static int isofs_rrip_exflag( p, ana )
343 ISO_RRIP_EXFLAG *p;
344 ISO_RRIP_ANALYZE *ana;
345 {
346 char buf[3];
347
348 buf[0] = p->h.type[0];
349 buf[1] = p->h.type[1];
350 buf[2] = 0x00;
351
352 printf("isofs:%s[%d] exflag=0x%x",
353 buf,
354 isonum_711(p->h.length),
355 p->flags );
356 return;
357 }
358
359 /*
360 * Unknown ...
361 * Nothing to do....
362 */
isofs_rrip_unknown(p,ana)363 static int isofs_rrip_unknown( p, ana )
364 ISO_RRIP_EXFLAG *p;
365 ISO_RRIP_ANALYZE *ana;
366 {
367 return;
368 }
369
370 typedef struct {
371 char type[2];
372 int (*func)();
373 int (*func2)();
374 int result;
375 } RRIP_TABLE;
376
377 static RRIP_TABLE rrip_table [] = {
378 { 'P', 'X', isofs_rrip_attr, isofs_rrip_defattr, ISO_SUSP_ATTR },
379 { 'T', 'F', isofs_rrip_tstamp, isofs_rrip_deftstamp, ISO_SUSP_TSTAMP },
380 { 'N', 'M', isofs_rrip_altname,0, ISO_SUSP_ALTNAME },
381 { 'C', 'L', isofs_rrip_clink, 0, ISO_SUSP_CLINK },
382 { 'P', 'L', isofs_rrip_plink, 0, ISO_SUSP_PLINK },
383 { 'S', 'L', isofs_rrip_slink, 0, ISO_SUSP_SLINK },
384 { 'R', 'E', isofs_rrip_reldir, 0, ISO_SUSP_RELDIR },
385 { 'P', 'N', isofs_rrip_device, 0, ISO_SUSP_DEVICE },
386 { 'R', 'R', isofs_rrip_idflag, 0, ISO_SUSP_IDFLAG },
387 { 'E', 'R', isofs_rrip_exflag, 0, ISO_SUSP_EXFLAG },
388 { 'S', 'P', isofs_rrip_unknown,0, ISO_SUSP_UNKNOWN },
389 { 'C', 'E', isofs_rrip_unknown,0, ISO_SUSP_UNKNOWN }
390 };
391
isofs_rrip_analyze(isodir,analyze)392 int isofs_rrip_analyze ( isodir, analyze )
393 struct iso_directory_record *isodir;
394 ISO_RRIP_ANALYZE *analyze;
395 {
396 register RRIP_TABLE *ptable;
397 register ISO_SUSP_HEADER *phead;
398 register ISO_SUSP_HEADER *pend;
399 int found;
400 int i;
401 char *pwhead;
402 int result;
403
404 /*
405 * Note: If name length is odd,
406 * it will be padding 1 byte after the name
407 */
408 pwhead = isodir->name + isonum_711(isodir->name_len);
409 if ( !(isonum_711(isodir->name_len) & 0x0001) )
410 pwhead ++;
411 phead = (ISO_SUSP_HEADER *)pwhead;
412 pend = (ISO_SUSP_HEADER *)( (char *)isodir + isonum_711(isodir->length) );
413
414 result = 0;
415 if ( pend == phead ) {
416 goto setdefault;
417 }
418 /*
419 * Note: "pend" should be more than one SUSP header
420 */
421 while ( pend >= phead + 1) {
422 found = 0;
423 for ( ptable=&rrip_table[0];ptable < &rrip_table[sizeof(rrip_table)/sizeof(RRIP_TABLE)]; ptable ++) {
424 if ( memcmp( phead->type, ptable->type, 2 ) == 0 ) {
425 found = 1;
426 ptable->func( phead, analyze );
427 result |= ptable->result;
428 break;
429 }
430 }
431 if ( found == 0 ) {
432 /*printf("isofs: name '");
433 for ( i =0; i < isonum_711(isodir->name_len) ;i++) {
434 printf("%c", *(isodir->name + i) );
435 }
436 printf("'");
437 printf(" - type %c%c [%08x/%08x]...not found\n",
438 phead->type[0], phead->type[1], phead, pend );
439 isofs_hexdump( phead, (int)( (char *)pend - (char *)phead ) );*/
440 break;
441 }
442
443 /*
444 * move to next SUSP
445 */
446 phead = (ISO_SUSP_HEADER *) ((unsigned)isonum_711(phead->length) + (char *)phead);
447 }
448
449 setdefault:
450 /*
451 * If we don't find the Basic SUSP stuffs, just set default value
452 * ( attribute/time stamp )
453 */
454 for ( ptable=&rrip_table[0];ptable < &rrip_table[2]; ptable ++) {
455 if ( ptable->func2 != 0 && !(ptable->result & result) ) {
456 ptable->func2( isodir, analyze );
457 }
458 }
459 return ( result );
460 }
461
462 /*
463 * Get Alternate Name from 'AL' record
464 * If either no AL record nor 0 lenght,
465 * it will be return the translated ISO9660 name,
466 */
isofs_rrip_getname(isodir,outbuf,outlen)467 int isofs_rrip_getname( isodir, outbuf, outlen )
468 struct iso_directory_record *isodir;
469 char *outbuf;
470 int *outlen;
471 {
472 ISO_SUSP_HEADER *phead, *pend;
473 ISO_RRIP_ALTNAME *p;
474 char *pwhead;
475 int found;
476
477 /*
478 * Note: If name length is odd,
479 * it will be padding 1 byte after the name
480 */
481 pwhead = isodir->name + isonum_711(isodir->name_len);
482 if ( !(isonum_711(isodir->name_len) & 0x0001) )
483 pwhead ++;
484 phead = (ISO_SUSP_HEADER *)pwhead;
485 pend = (ISO_SUSP_HEADER *)( (char *)isodir + isonum_711(isodir->length) );
486
487 found = 0;
488 if ( pend != phead ) {
489 while ( pend >= phead + 1) {
490 if ( memcmp( phead->type, "NM", 2 ) == 0 ) {
491 found = 1;
492 break;
493 }
494 phead = (ISO_SUSP_HEADER *) ((unsigned)isonum_711(phead->length) + (char *)phead);
495 }
496 }
497 if ( found == 1 ) {
498 p = (ISO_RRIP_ALTNAME *)phead;
499 *outlen = isonum_711( p->h.length ) - sizeof( ISO_RRIP_ALTNAME );
500 memcpy(outbuf, (char *)( &p->flags + 1 ), *outlen );
501 } else {
502 isofntrans(isodir->name, isonum_711(isodir->name_len), outbuf, outlen );
503 if ( *outlen == 1) {
504 switch ( outbuf[0] ) {
505 case 0:
506 outbuf[0] = '.';
507 break;
508 case 1:
509 outbuf[0] = '.';
510 outbuf[1] = '.';
511 *outlen = 2;
512 }
513 }
514 }
515 return( found );
516 }
517
518 /*
519 * Get Symbolic Name from 'SL' record
520 *
521 * Note: isodir should contains SL record!
522 */
isofs_rrip_getsymname(vp,isodir,outbuf,outlen)523 int isofs_rrip_getsymname( vp, isodir, outbuf, outlen )
524 struct vnode *vp;
525 struct iso_directory_record *isodir;
526 char *outbuf;
527 int *outlen;
528 {
529 register ISO_RRIP_SLINK_COMPONENT *pcomp;
530 register ISO_SUSP_HEADER *phead, *pend;
531 register ISO_RRIP_SLINK_COMPONENT *pcompe;
532 ISO_RRIP_SLINK *p;
533 char *pwhead;
534 int found;
535 int slash;
536 int wlen;
537
538 /*
539 * Note: If name length is odd,
540 * it will be padding 1 byte after the name
541 */
542 /* printf("sym:%s ", isodir->name); */
543 pwhead = isodir->name + isonum_711(isodir->name_len);
544 if ( !(isonum_711(isodir->name_len) & 0x0001) )
545 pwhead ++;
546 phead = (ISO_SUSP_HEADER *)pwhead;
547 pend = (ISO_SUSP_HEADER *)( (char *)isodir + isonum_711(isodir->length) );
548
549 found = 0;
550 if ( pend != phead ) {
551 while ( pend >= phead + 1) {
552 if ( memcmp( phead->type, "SL", 2 ) == 0 ) {
553 found = 1;
554 break;
555 }
556 phead = (ISO_SUSP_HEADER *) ((unsigned)isonum_711(phead->length) + (char *)phead);
557 }
558 }
559 if ( found == 0 ) {
560 *outlen = 0;
561 return( found );
562 }
563
564 p = (ISO_RRIP_SLINK *)phead;
565 pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
566 pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
567
568 /*
569 * Gathering a Symbolic name from each component with path
570 */
571 *outlen = 0;
572 slash = 0;
573 while ( pcomp < pcompe ) {
574
575 /* Inserting Current */
576 if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_CURRENT ) {
577 /* printf("C "); */
578 memcpy(outbuf+*outlen, "./", 2);
579 *outlen += 2;
580 slash = 0;
581 }
582
583 /* Inserting Parent */
584 if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_PARENT ) {
585 memcpy(outbuf+*outlen, "../", 3);
586 *outlen += 3;
587 slash = 0;
588 }
589
590 /* Inserting slash for ROOT */
591 if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_ROOT ) {
592 /*printf("R "); */
593 memcpy(outbuf+*outlen, "/", 1);
594 *outlen += 1;
595 slash = 0;
596 }
597
598 /* Inserting a mount point i.e. "/cdrom" */
599 if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_VOLROOT ) {
600 wlen = strlen(vp->v_mount->mnt_stat.f_mntonname);
601 memcpy(outbuf+*outlen, vp->v_mount->mnt_stat.f_mntonname, wlen);
602 *outlen += wlen;
603 slash = 1;
604 }
605
606 /* Inserting hostname i.e. "tama:" */
607 if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_HOST ) {
608 memcpy(outbuf+*outlen, hostname, hostnamelen);
609 *(outbuf+hostnamelen) = ':';
610 *outlen += (hostnamelen + 1);
611 slash = 0; /* Uuum Should we insert a slash ? */
612 }
613
614 /* Inserting slash for next component */
615 if ( slash == 1 ) {
616 outbuf[*outlen] = '/';
617 *outlen += 1;
618 slash = 0;
619 }
620
621 /* Inserting component */
622 wlen = isonum_711(pcomp->clen);
623 if ( wlen != 0 ) {
624 /*printf("C%s|%d ", pcomp->name);*/
625 memcpy(outbuf + *outlen, pcomp->name, wlen );
626 *outlen += wlen;
627 slash = 1;
628 }
629
630 /*
631 * Move to next component...
632 */
633 pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp
634 + sizeof(ISO_RRIP_SLINK_COMPONENT) - 1
635 + isonum_711(pcomp->clen));
636 }
637 /*printf("O%s|%d ", outbuf, *outlen);*/
638 return( found );
639 }
640
641 #ifdef nope
642 /* Hexdump routine for debug*/
isofs_hexdump(p,size)643 int isofs_hexdump( p, size )
644 unsigned char *p;
645 int size;
646 {
647 int i,j,k;
648 unsigned char *wp;
649
650 for ( i = 0; i < size; i += 16 ) {
651 printf("isofs: ");
652 wp = p;
653 k = ( (size - i) > 16 ? 16 : size - i );
654 for ( j =0; j < k; j ++ ){
655 printf("%02x ", *p );
656 p++;
657 }
658 printf(" : ");
659 p = wp;
660 for ( j =0; j < k; j ++ ){
661 if ( (*p > 0x20) && (*p < 0x7f) )
662 printf("%c", *p );
663 else
664 printf(" ");
665 p++;
666 }
667 printf("\n");
668 }
669 printf("\n");
670 }
671 #endif
672