This source file includes following definitions.
- ntfs_ntvattrrele
- ntfs_findvattr
- ntfs_ntvattrget
- ntfs_loadntnode
- ntfs_ntget
- ntfs_ntlookup
- ntfs_ntput
- ntfs_ntref
- ntfs_ntrele
- ntfs_freentvattr
- ntfs_attrtontvattr
- ntfs_runtovrun
- ntfs_uastricmp
- ntfs_uastrcmp
- ntfs_fget
- ntfs_frele
- ntfs_ntlookupattr
- ntfs_ntlookupfile
- ntfs_isnamepermitted
- ntfs_ntreaddir
- ntfs_nttimetounix
- ntfs_times
- ntfs_filesize
- ntfs_writeattr_plain
- ntfs_writentvattr_plain
- ntfs_readntvattr_plain
- ntfs_readattr_plain
- ntfs_readattr
- ntfs_parserun
- ntfs_procfixups
- ntfs_runtocn
- ntfs_toupper_init
- ntfs_toupper_use
- ntfs_toupper_unuse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include <sys/cdefs.h>
33 #ifdef __KERNEL_RCSID
34 __KERNEL_RCSID(0, "$NetBSD: ntfs_subr.c,v 1.4 2003/04/10 21:37:32 jdolecek Exp $");
35 #endif
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/namei.h>
40 #include <sys/proc.h>
41 #include <sys/kernel.h>
42 #include <sys/vnode.h>
43 #include <sys/mount.h>
44 #include <sys/buf.h>
45 #include <sys/file.h>
46 #include <sys/malloc.h>
47 #include <sys/lock.h>
48 #if defined(__FreeBSD__)
49 #include <machine/clock.h>
50 #endif
51
52 #include <miscfs/specfs/specdev.h>
53
54
55 #if defined(__FreeBSD__) || defined(__NetBSD__)
56 #include <fs/ntfs/ntfs.h>
57 #include <fs/ntfs/ntfsmount.h>
58 #include <fs/ntfs/ntfs_inode.h>
59 #include <fs/ntfs/ntfs_vfsops.h>
60 #include <fs/ntfs/ntfs_subr.h>
61 #include <fs/ntfs/ntfs_compr.h>
62 #include <fs/ntfs/ntfs_ihash.h>
63 #else
64 #include <ntfs/ntfs.h>
65 #include <ntfs/ntfsmount.h>
66 #include <ntfs/ntfs_inode.h>
67 #include <ntfs/ntfs_vfsops.h>
68 #include <ntfs/ntfs_subr.h>
69 #include <ntfs/ntfs_compr.h>
70 #include <ntfs/ntfs_ihash.h>
71 #endif
72
73 #if defined(NTFS_DEBUG)
74 int ntfs_debug = NTFS_DEBUG;
75 #endif
76
77 #ifdef MALLOC_DEFINE
78 MALLOC_DEFINE(M_NTFSNTVATTR, "NTFS vattr", "NTFS file attribute information");
79 MALLOC_DEFINE(M_NTFSRDATA, "NTFS res data", "NTFS resident data");
80 MALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage");
81 MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary");
82 #endif
83
84
85 struct ntfs_lookup_ctx {
86 u_int32_t aoff;
87 u_int32_t rdsize;
88 cn_t cn;
89 struct ntfs_lookup_ctx *prev;
90 };
91
92 static int ntfs_ntlookupattr(struct ntfsmount *, const char *, int, int *, char **);
93 static int ntfs_findvattr(struct ntfsmount *, struct ntnode *, struct ntvattr **, struct ntvattr **, u_int32_t, const char *, size_t, cn_t);
94 static int ntfs_uastricmp(struct ntfsmount *, const wchar *, size_t, const char *, size_t);
95 static int ntfs_uastrcmp(struct ntfsmount *, const wchar *, size_t, const char *, size_t);
96
97
98
99 static wchar *ntfs_toupper_tab;
100 #define NTFS_U28(ch) ((((ch) & 0xE0) == 0) ? '_' : (ch) & 0xFF)
101 #define NTFS_TOUPPER(ch) (ntfs_toupper_tab[(unsigned char)(ch)])
102 static struct lock ntfs_toupper_lock;
103 static signed int ntfs_toupper_usecount;
104
105
106 #define NTFS_AALPCMP(aalp,type,name,namelen) ( \
107 (aalp->al_type == type) && (aalp->al_namelen == namelen) && \
108 !ntfs_uastrcmp(ntmp, aalp->al_name,aalp->al_namelen,name,namelen) )
109
110
111
112
113 int
114 ntfs_ntvattrrele(vap)
115 struct ntvattr * vap;
116 {
117 dprintf(("ntfs_ntvattrrele: ino: %d, type: 0x%x\n",
118 vap->va_ip->i_number, vap->va_type));
119
120 ntfs_ntrele(vap->va_ip);
121
122 return (0);
123 }
124
125
126
127
128 static int
129 ntfs_findvattr(ntmp, ip, lvapp, vapp, type, name, namelen, vcn)
130 struct ntfsmount *ntmp;
131 struct ntnode *ip;
132 struct ntvattr **lvapp, **vapp;
133 u_int32_t type;
134 const char *name;
135 size_t namelen;
136 cn_t vcn;
137 {
138 int error;
139 struct ntvattr *vap;
140
141 if((ip->i_flag & IN_LOADED) == 0) {
142 dprintf(("ntfs_findvattr: node not loaded, ino: %d\n",
143 ip->i_number));
144 error = ntfs_loadntnode(ntmp,ip);
145 if (error) {
146 printf("ntfs_findvattr: FAILED TO LOAD INO: %d\n",
147 ip->i_number);
148 return (error);
149 }
150 }
151
152 *lvapp = NULL;
153 *vapp = NULL;
154 LIST_FOREACH(vap, &ip->i_valist, va_list) {
155 ddprintf(("ntfs_findvattr: type: 0x%x, vcn: %d - %d\n", \
156 vap->va_type, (u_int32_t) vap->va_vcnstart, \
157 (u_int32_t) vap->va_vcnend));
158 if ((vap->va_type == type) &&
159 (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) &&
160 (vap->va_namelen == namelen) &&
161 (strncmp(name, vap->va_name, namelen) == 0)) {
162 *vapp = vap;
163 ntfs_ntref(vap->va_ip);
164 return (0);
165 }
166 if (vap->va_type == NTFS_A_ATTRLIST)
167 *lvapp = vap;
168 }
169
170 return (-1);
171 }
172
173
174
175
176
177
178
179
180 int
181 ntfs_ntvattrget(
182 struct ntfsmount * ntmp,
183 struct ntnode * ip,
184 u_int32_t type,
185 const char *name,
186 cn_t vcn,
187 struct ntvattr ** vapp)
188 {
189 struct ntvattr *lvap = NULL;
190 struct attr_attrlist *aalp;
191 struct attr_attrlist *nextaalp;
192 struct vnode *newvp;
193 struct ntnode *newip;
194 caddr_t alpool;
195 size_t namelen, len;
196 int error;
197
198 *vapp = NULL;
199
200 if (name) {
201 dprintf(("ntfs_ntvattrget: " \
202 "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \
203 ip->i_number, type, name, (u_int32_t) vcn));
204 namelen = strlen(name);
205 } else {
206 dprintf(("ntfs_ntvattrget: " \
207 "ino: %d, type: 0x%x, vcn: %d\n", \
208 ip->i_number, type, (u_int32_t) vcn));
209 name = "";
210 namelen = 0;
211 }
212
213 error = ntfs_findvattr(ntmp, ip, &lvap, vapp, type, name, namelen, vcn);
214 if (error >= 0)
215 return (error);
216
217 if (!lvap) {
218 dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \
219 "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \
220 ip->i_number, type, name, (u_int32_t) vcn));
221 return (ENOENT);
222 }
223
224 len = lvap->va_datalen;
225 alpool = (caddr_t) malloc(len, M_TEMP, M_WAITOK);
226 error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len,
227 NULL);
228 if (error)
229 goto out;
230
231 aalp = (struct attr_attrlist *) alpool;
232 nextaalp = NULL;
233
234 for(; len > 0; aalp = nextaalp) {
235 dprintf(("ntfs_ntvattrget: " \
236 "attrlist: ino: %d, attr: 0x%x, vcn: %d\n", \
237 aalp->al_inumber, aalp->al_type, \
238 (u_int32_t) aalp->al_vcnstart));
239
240 if (len > aalp->reclen) {
241 nextaalp = NTFS_NEXTREC(aalp, struct attr_attrlist *);
242 } else {
243 nextaalp = NULL;
244 }
245 len -= aalp->reclen;
246
247 if (!NTFS_AALPCMP(aalp, type, name, namelen) ||
248 (nextaalp && (nextaalp->al_vcnstart <= vcn) &&
249 NTFS_AALPCMP(nextaalp, type, name, namelen)))
250 continue;
251
252 dprintf(("ntfs_ntvattrget: attribute in ino: %d\n",
253 aalp->al_inumber));
254
255
256
257 error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber,
258 NTFS_A_DATA, NULL, LK_EXCLUSIVE,
259 VG_EXT, curproc, &newvp);
260 if (error) {
261 printf("ntfs_ntvattrget: CAN'T VGET INO: %d\n",
262 aalp->al_inumber);
263 goto out;
264 }
265 newip = VTONT(newvp);
266
267 error = ntfs_findvattr(ntmp, newip, &lvap, vapp,
268 type, name, namelen, vcn);
269 vput(newvp);
270 if (error == 0)
271 goto out;
272 printf("ntfs_ntvattrget: ATTRLIST ERROR.\n");
273 break;
274 }
275 error = ENOENT;
276
277 dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \
278 "ino: %d, type: 0x%x, name: %.*s, vcn: %d\n", \
279 ip->i_number, type, (int) namelen, name, (u_int32_t) vcn));
280 out:
281 free(alpool, M_TEMP);
282 return (error);
283 }
284
285
286
287
288
289
290 int
291 ntfs_loadntnode(
292 struct ntfsmount * ntmp,
293 struct ntnode * ip)
294 {
295 struct filerec *mfrp;
296 daddr64_t bn;
297 int error,off;
298 struct attr *ap;
299 struct ntvattr *nvap;
300
301 dprintf(("ntfs_loadntnode: loading ino: %d\n",ip->i_number));
302
303 mfrp = (struct filerec *) malloc(ntfs_bntob(ntmp->ntm_bpmftrec),
304 M_TEMP, M_WAITOK);
305
306 if (ip->i_number < NTFS_SYSNODESNUM) {
307 struct buf *bp;
308
309 dprintf(("ntfs_loadntnode: read system node\n"));
310
311 bn = ntfs_cntobn(ntmp->ntm_mftcn) +
312 ntmp->ntm_bpmftrec * ip->i_number;
313
314 error = bread(ntmp->ntm_devvp,
315 bn, ntfs_bntob(ntmp->ntm_bpmftrec),
316 NOCRED, &bp);
317 if (error) {
318 printf("ntfs_loadntnode: BREAD FAILED\n");
319 brelse(bp);
320 goto out;
321 }
322 memcpy(mfrp, bp->b_data, ntfs_bntob(ntmp->ntm_bpmftrec));
323 bqrelse(bp);
324 } else {
325 struct vnode *vp;
326
327 vp = ntmp->ntm_sysvn[NTFS_MFTINO];
328 error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
329 ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec),
330 ntfs_bntob(ntmp->ntm_bpmftrec), mfrp, NULL);
331 if (error) {
332 printf("ntfs_loadntnode: ntfs_readattr failed\n");
333 goto out;
334 }
335 }
336
337
338 error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp,
339 ntfs_bntob(ntmp->ntm_bpmftrec));
340 if (error) {
341 printf("ntfs_loadntnode: BAD MFT RECORD %d\n",
342 (u_int32_t) ip->i_number);
343 goto out;
344 }
345
346 dprintf(("ntfs_loadntnode: load attrs for ino: %d\n",ip->i_number));
347 off = mfrp->fr_attroff;
348 ap = (struct attr *) ((caddr_t)mfrp + off);
349
350 LIST_INIT(&ip->i_valist);
351
352 while (ap->a_hdr.a_type != -1) {
353 error = ntfs_attrtontvattr(ntmp, &nvap, ap);
354 if (error)
355 break;
356 nvap->va_ip = ip;
357
358 LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list);
359
360 off += ap->a_hdr.reclen;
361 ap = (struct attr *) ((caddr_t)mfrp + off);
362 }
363 if (error) {
364 printf("ntfs_loadntnode: failed to load attr ino: %d\n",
365 ip->i_number);
366 goto out;
367 }
368
369 ip->i_mainrec = mfrp->fr_mainrec;
370 ip->i_nlink = mfrp->fr_nlink;
371 ip->i_frflag = mfrp->fr_flags;
372
373 ip->i_flag |= IN_LOADED;
374
375 out:
376 free(mfrp, M_TEMP);
377 return (error);
378 }
379
380
381
382
383
384 int
385 ntfs_ntget(
386 struct ntnode *ip,
387 #ifdef __OpenBSD__
388 struct proc *p
389 #endif
390 )
391 {
392 dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n",
393 ip->i_number, ip, ip->i_usecount));
394
395 ip->i_usecount++;
396
397 lockmgr(&ip->i_lock, LK_EXCLUSIVE, NULL);
398
399 return 0;
400 }
401
402
403
404
405
406
407
408
409 int
410 ntfs_ntlookup(
411 struct ntfsmount * ntmp,
412 ino_t ino,
413 #ifndef __OpenBSD__
414 struct ntnode ** ipp)
415 #else
416 struct ntnode ** ipp,
417 struct proc * p)
418 #endif
419 {
420 struct ntnode *ip;
421
422 dprintf(("ntfs_ntlookup: looking for ntnode %d\n", ino));
423
424 do {
425 if ((ip = ntfs_nthashlookup(ntmp->ntm_dev, ino)) != NULL) {
426 #ifndef __OpenBSD__
427 ntfs_ntget(ip);
428 #else
429 ntfs_ntget(ip, p);
430 #endif
431 dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
432 ino, ip, ip->i_usecount));
433 *ipp = ip;
434 return (0);
435 }
436 } while (lockmgr(&ntfs_hashlock, LK_EXCLUSIVE | LK_SLEEPFAIL, NULL));
437
438 MALLOC(ip, struct ntnode *, sizeof(struct ntnode),
439 M_NTFSNTNODE, M_WAITOK);
440 ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip));
441 bzero((caddr_t) ip, sizeof(struct ntnode));
442
443
444 ip->i_devvp = ntmp->ntm_devvp;
445 ip->i_dev = ntmp->ntm_dev;
446 ip->i_number = ino;
447 ip->i_mp = ntmp;
448
449 LIST_INIT(&ip->i_fnlist);
450 VREF(ip->i_devvp);
451
452
453 lockinit(&ip->i_lock, PINOD, "ntnode", 0, LK_EXCLUSIVE);
454 #ifndef __OpenBSD__
455 ntfs_ntget(ip);
456 #else
457 ntfs_ntget(ip, p);
458 #endif
459
460 ntfs_nthashins(ip);
461
462 lockmgr(&ntfs_hashlock, LK_RELEASE, NULL);
463
464 *ipp = ip;
465
466 dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n",
467 ino, ip, ip->i_usecount));
468
469 return (0);
470 }
471
472
473
474
475
476
477
478 void
479 ntfs_ntput(
480 struct ntnode *ip,
481 #ifdef __OpenBSD__
482 struct proc *p
483 #endif
484 )
485 {
486 struct ntvattr *vap;
487
488 dprintf(("ntfs_ntput: rele ntnode %d: %p, usecount: %d\n",
489 ip->i_number, ip, ip->i_usecount));
490
491 ip->i_usecount--;
492
493 #ifdef DIAGNOSTIC
494 if (ip->i_usecount < 0) {
495 panic("ntfs_ntput: ino: %d usecount: %d ",
496 ip->i_number,ip->i_usecount);
497 }
498 #endif
499
500 if (ip->i_usecount > 0) {
501 lockmgr(&ip->i_lock, LK_RELEASE, NULL);
502 return;
503 }
504
505 dprintf(("ntfs_ntput: deallocating ntnode: %d\n", ip->i_number));
506
507 if (LIST_FIRST(&ip->i_fnlist))
508 panic("ntfs_ntput: ntnode has fnodes");
509
510 ntfs_nthashrem(ip);
511
512 while ((vap = LIST_FIRST(&ip->i_valist)) != NULL) {
513 LIST_REMOVE(vap, va_list);
514 ntfs_freentvattr(vap);
515 }
516
517 vrele(ip->i_devvp);
518 FREE(ip, M_NTFSNTNODE);
519 }
520
521
522
523
524 void
525 ntfs_ntref(ip)
526 struct ntnode *ip;
527 {
528 ip->i_usecount++;
529
530 dprintf(("ntfs_ntref: ino %d, usecount: %d\n",
531 ip->i_number, ip->i_usecount));
532
533 }
534
535
536
537
538 void
539 ntfs_ntrele(ip)
540 struct ntnode *ip;
541 {
542 dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n",
543 ip->i_number, ip, ip->i_usecount));
544
545 ip->i_usecount--;
546
547 if (ip->i_usecount < 0)
548 panic("ntfs_ntrele: ino: %d usecount: %d ",
549 ip->i_number,ip->i_usecount);
550 }
551
552
553
554
555 void
556 ntfs_freentvattr(vap)
557 struct ntvattr * vap;
558 {
559 if (vap->va_flag & NTFS_AF_INRUN) {
560 if (vap->va_vruncn)
561 free(vap->va_vruncn, M_NTFSRUN);
562 if (vap->va_vruncl)
563 free(vap->va_vruncl, M_NTFSRUN);
564 } else {
565 if (vap->va_datap)
566 free(vap->va_datap, M_NTFSRDATA);
567 }
568 FREE(vap, M_NTFSNTVATTR);
569 }
570
571
572
573
574
575 int
576 ntfs_attrtontvattr(
577 struct ntfsmount * ntmp,
578 struct ntvattr ** rvapp,
579 struct attr * rap)
580 {
581 int error, i;
582 struct ntvattr *vap;
583
584 error = 0;
585 *rvapp = NULL;
586
587 MALLOC(vap, struct ntvattr *, sizeof(struct ntvattr),
588 M_NTFSNTVATTR, M_WAITOK);
589 bzero(vap, sizeof(struct ntvattr));
590 vap->va_ip = NULL;
591 vap->va_flag = rap->a_hdr.a_flag;
592 vap->va_type = rap->a_hdr.a_type;
593 vap->va_compression = rap->a_hdr.a_compression;
594 vap->va_index = rap->a_hdr.a_index;
595
596 ddprintf(("type: 0x%x, index: %d", vap->va_type, vap->va_index));
597
598 vap->va_namelen = rap->a_hdr.a_namelen;
599 if (rap->a_hdr.a_namelen) {
600 wchar *unp = (wchar *) ((caddr_t) rap + rap->a_hdr.a_nameoff);
601 ddprintf((", name:["));
602 for (i = 0; i < vap->va_namelen; i++) {
603 vap->va_name[i] = unp[i];
604 ddprintf(("%c", vap->va_name[i]));
605 }
606 ddprintf(("]"));
607 }
608 if (vap->va_flag & NTFS_AF_INRUN) {
609 ddprintf((", nonres."));
610 vap->va_datalen = rap->a_nr.a_datalen;
611 vap->va_allocated = rap->a_nr.a_allocated;
612 vap->va_vcnstart = rap->a_nr.a_vcnstart;
613 vap->va_vcnend = rap->a_nr.a_vcnend;
614 vap->va_compressalg = rap->a_nr.a_compressalg;
615 error = ntfs_runtovrun(&(vap->va_vruncn), &(vap->va_vruncl),
616 &(vap->va_vruncnt),
617 (caddr_t) rap + rap->a_nr.a_dataoff);
618 } else {
619 vap->va_compressalg = 0;
620 ddprintf((", res."));
621 vap->va_datalen = rap->a_r.a_datalen;
622 vap->va_allocated = rap->a_r.a_datalen;
623 vap->va_vcnstart = 0;
624 vap->va_vcnend = ntfs_btocn(vap->va_allocated);
625 vap->va_datap = (caddr_t) malloc(vap->va_datalen,
626 M_NTFSRDATA, M_WAITOK);
627 memcpy(vap->va_datap, (caddr_t) rap + rap->a_r.a_dataoff,
628 rap->a_r.a_datalen);
629 }
630 ddprintf((", len: %d", vap->va_datalen));
631
632 if (error)
633 FREE(vap, M_NTFSNTVATTR);
634 else
635 *rvapp = vap;
636
637 ddprintf(("\n"));
638
639 return (error);
640 }
641
642
643
644
645 int
646 ntfs_runtovrun(
647 cn_t ** rcnp,
648 cn_t ** rclp,
649 u_long * rcntp,
650 u_int8_t * run)
651 {
652 u_int32_t off;
653 u_int32_t sz, i;
654 cn_t *cn;
655 cn_t *cl;
656 u_long cnt;
657 cn_t prev;
658 cn_t tmp;
659
660 off = 0;
661 cnt = 0;
662 i = 0;
663 while (run[off]) {
664 off += (run[off] & 0xF) + ((run[off] >> 4) & 0xF) + 1;
665 cnt++;
666 }
667 cn = (cn_t *) malloc(cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK);
668 cl = (cn_t *) malloc(cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK);
669
670 off = 0;
671 cnt = 0;
672 prev = 0;
673 while (run[off]) {
674
675 sz = run[off++];
676 cl[cnt] = 0;
677
678 for (i = 0; i < (sz & 0xF); i++)
679 cl[cnt] += (u_int32_t) run[off++] << (i << 3);
680
681 sz >>= 4;
682 if (run[off + sz - 1] & 0x80) {
683 tmp = ((u_int64_t) - 1) << (sz << 3);
684 for (i = 0; i < sz; i++)
685 tmp |= (u_int64_t) run[off++] << (i << 3);
686 } else {
687 tmp = 0;
688 for (i = 0; i < sz; i++)
689 tmp |= (u_int64_t) run[off++] << (i << 3);
690 }
691 if (tmp)
692 prev = cn[cnt] = prev + tmp;
693 else
694 cn[cnt] = tmp;
695
696 cnt++;
697 }
698 *rcnp = cn;
699 *rclp = cl;
700 *rcntp = cnt;
701 return (0);
702 }
703
704
705
706
707 static int
708 ntfs_uastricmp(ntmp, ustr, ustrlen, astr, astrlen)
709 struct ntfsmount *ntmp;
710 const wchar *ustr;
711 size_t ustrlen;
712 const char *astr;
713 size_t astrlen;
714 {
715 size_t i;
716 int res;
717 const char *astrend = astr + astrlen;
718
719 for (i = 0; i < ustrlen && astr < astrend; i++) {
720 res = (*ntmp->ntm_wcmp)(NTFS_TOUPPER(ustr[i]),
721 NTFS_TOUPPER((*ntmp->ntm_wget)(&astr)) );
722 if (res)
723 return res;
724 }
725
726 if (i == ustrlen && astr == astrend)
727 return 0;
728 else if (i == ustrlen)
729 return -1;
730 else
731 return 1;
732 }
733
734
735
736
737 static int
738 ntfs_uastrcmp(ntmp, ustr, ustrlen, astr, astrlen)
739 struct ntfsmount *ntmp;
740 const wchar *ustr;
741 size_t ustrlen;
742 const char *astr;
743 size_t astrlen;
744 {
745 size_t i;
746 int res;
747 const char *astrend = astr + astrlen;
748
749 for (i = 0; (i < ustrlen) && (astr < astrend); i++) {
750 res = (*ntmp->ntm_wcmp)(ustr[i], (*ntmp->ntm_wget)(&astr));
751 if (res)
752 return res;
753 }
754
755 if (i == ustrlen && astr == astrend)
756 return 0;
757 else if (i == ustrlen)
758 return -1;
759 else
760 return 1;
761 }
762
763
764
765
766
767
768 int
769 ntfs_fget(
770 struct ntfsmount *ntmp,
771 struct ntnode *ip,
772 int attrtype,
773 char *attrname,
774 struct fnode **fpp)
775 {
776 struct fnode *fp;
777
778 dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n",
779 ip->i_number,attrtype, attrname?attrname:""));
780 *fpp = NULL;
781 LIST_FOREACH(fp, &ip->i_fnlist, f_fnlist) {
782 dprintf(("ntfs_fget: fnode: attrtype: %d, attrname: %s\n",
783 fp->f_attrtype, fp->f_attrname?fp->f_attrname:""));
784
785 if ((attrtype == fp->f_attrtype) &&
786 ((!attrname && !fp->f_attrname) ||
787 (attrname && fp->f_attrname &&
788 !strcmp(attrname,fp->f_attrname)))){
789 dprintf(("ntfs_fget: found existed: %p\n",fp));
790 *fpp = fp;
791 }
792 }
793
794 if (*fpp)
795 return (0);
796
797 MALLOC(fp, struct fnode *, sizeof(struct fnode), M_NTFSFNODE, M_WAITOK);
798 bzero(fp, sizeof(struct fnode));
799 dprintf(("ntfs_fget: allocating fnode: %p\n",fp));
800
801 fp->f_ip = ip;
802 fp->f_attrname = attrname;
803 if (fp->f_attrname) fp->f_flag |= FN_AATTRNAME;
804 fp->f_attrtype = attrtype;
805
806 ntfs_ntref(ip);
807
808 LIST_INSERT_HEAD(&ip->i_fnlist, fp, f_fnlist);
809
810 *fpp = fp;
811
812 return (0);
813 }
814
815
816
817
818
819
820 void
821 ntfs_frele(
822 struct fnode *fp)
823 {
824 struct ntnode *ip = FTONT(fp);
825
826 dprintf(("ntfs_frele: fnode: %p for %d: %p\n", fp, ip->i_number, ip));
827
828 dprintf(("ntfs_frele: deallocating fnode\n"));
829 LIST_REMOVE(fp,f_fnlist);
830 if (fp->f_flag & FN_AATTRNAME)
831 FREE(fp->f_attrname, M_TEMP);
832 if (fp->f_dirblbuf)
833 FREE(fp->f_dirblbuf, M_NTFSDIR);
834 FREE(fp, M_NTFSFNODE);
835 ntfs_ntrele(ip);
836 }
837
838
839
840
841
842
843 static int
844 ntfs_ntlookupattr(
845 struct ntfsmount * ntmp,
846 const char * name,
847 int namelen,
848 int *attrtype,
849 char **attrname)
850 {
851 const char *sys;
852 size_t syslen, i;
853 struct ntvattrdef *adp;
854
855 if (namelen == 0)
856 return (0);
857
858 if (name[0] == '$') {
859 sys = name;
860 for (syslen = 0; syslen < namelen; syslen++) {
861 if(sys[syslen] == ':') {
862 name++;
863 namelen--;
864 break;
865 }
866 }
867 name += syslen;
868 namelen -= syslen;
869
870 adp = ntmp->ntm_ad;
871 for (i = 0; i < ntmp->ntm_adnum; i++, adp++){
872 if (syslen != adp->ad_namelen ||
873 strncmp(sys, adp->ad_name, syslen) != 0)
874 continue;
875
876 *attrtype = adp->ad_type;
877 goto out;
878 }
879 return (ENOENT);
880 }
881
882 out:
883 if (namelen) {
884 *attrname = (char *) malloc(namelen, M_TEMP, M_WAITOK);
885 memcpy((*attrname), name, namelen);
886 (*attrname)[namelen] = '\0';
887 *attrtype = NTFS_A_DATA;
888 }
889
890 return (0);
891 }
892
893
894
895
896
897 int
898 ntfs_ntlookupfile(
899 struct ntfsmount * ntmp,
900 struct vnode * vp,
901 struct componentname * cnp,
902 #ifndef __OpenBSD__
903 struct vnode ** vpp)
904 #else
905 struct vnode ** vpp,
906 struct proc *p)
907 #endif
908 {
909 struct fnode *fp = VTOF(vp);
910 struct ntnode *ip = FTONT(fp);
911 struct ntvattr *vap;
912 cn_t cn = 0;
913 caddr_t rdbuf;
914 u_int32_t blsize;
915 u_int32_t rdsize;
916 struct attr_indexentry *iep;
917 int error, res, anamelen, fnamelen;
918 const char *fname,*aname;
919 u_int32_t aoff;
920 int attrtype = NTFS_A_DATA;
921 char *attrname = NULL;
922 struct fnode *nfp;
923 struct vnode *nvp;
924 enum vtype f_type;
925 int fullscan = 0;
926 struct ntfs_lookup_ctx *lookup_ctx = NULL, *tctx;
927
928 #ifndef __OpenBSD__
929 error = ntfs_ntget(ip);
930 #else
931 error = ntfs_ntget(ip, p);
932 #endif
933 if (error)
934 return (error);
935
936 error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap);
937 if (error || (vap->va_flag & NTFS_AF_INRUN))
938 return (ENOTDIR);
939
940
941
942
943
944 fname = cnp->cn_nameptr;
945 aname = NULL;
946 anamelen = 0;
947 for (fnamelen = 0; fnamelen < cnp->cn_namelen; fnamelen++)
948 if(fname[fnamelen] == ':') {
949 aname = fname + fnamelen + 1;
950 anamelen = cnp->cn_namelen - fnamelen - 1;
951 dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n",
952 fname, fnamelen, aname, anamelen));
953 break;
954 }
955
956 blsize = vap->va_a_iroot->ir_size;
957 dprintf(("ntfs_ntlookupfile: blksz: %d\n", blsize));
958
959 rdbuf = (caddr_t) malloc(blsize, M_TEMP, M_WAITOK);
960
961 loop:
962 rdsize = vap->va_datalen;
963 dprintf(("ntfs_ntlookupfile: rdsz: %d\n", rdsize));
964
965 error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30",
966 0, rdsize, rdbuf, NULL);
967 if (error)
968 goto fail;
969
970 aoff = sizeof(struct attr_indexroot);
971
972 do {
973 iep = (struct attr_indexentry *) (rdbuf + aoff);
974
975 for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff);
976 aoff += iep->reclen,
977 iep = (struct attr_indexentry *) (rdbuf + aoff))
978 {
979 ddprintf(("scan: %d, %d\n",
980 (u_int32_t) iep->ie_number,
981 (u_int32_t) iep->ie_fnametype));
982
983
984
985
986 res = ntfs_uastricmp(ntmp, iep->ie_fname,
987 iep->ie_fnamelen, fname, fnamelen);
988 if (!fullscan) {
989 if (res > 0) break;
990 if (res < 0) continue;
991 }
992
993 if (iep->ie_fnametype == 0 ||
994 !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS))
995 {
996 res = ntfs_uastrcmp(ntmp, iep->ie_fname,
997 iep->ie_fnamelen, fname, fnamelen);
998 if (res != 0 && !fullscan) continue;
999 }
1000
1001
1002
1003 if (fullscan && res != 0) {
1004 if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) {
1005 MALLOC(tctx, struct ntfs_lookup_ctx *,
1006 sizeof(struct ntfs_lookup_ctx),
1007 M_TEMP, M_WAITOK);
1008 tctx->aoff = aoff + iep->reclen;
1009 tctx->rdsize = rdsize;
1010 tctx->cn = cn;
1011 tctx->prev = lookup_ctx;
1012 lookup_ctx = tctx;
1013 break;
1014 } else
1015 continue;
1016 }
1017
1018 if (aname) {
1019 error = ntfs_ntlookupattr(ntmp,
1020 aname, anamelen,
1021 &attrtype, &attrname);
1022 if (error)
1023 goto fail;
1024 }
1025
1026
1027 if ((iep->ie_number == ip->i_number) &&
1028 (attrtype == fp->f_attrtype) &&
1029 ((!attrname && !fp->f_attrname) ||
1030 (attrname && fp->f_attrname &&
1031 !strcmp(attrname, fp->f_attrname))))
1032 {
1033 VREF(vp);
1034 *vpp = vp;
1035 error = 0;
1036 goto fail;
1037 }
1038
1039
1040 if (attrname) {
1041 FREE(attrname, M_TEMP);
1042 attrname = NULL;
1043 }
1044
1045
1046 error = ntfs_vgetex(ntmp->ntm_mountp,
1047 iep->ie_number, attrtype, attrname,
1048 LK_EXCLUSIVE, VG_DONTLOADIN | VG_DONTVALIDFN,
1049 curproc, &nvp);
1050 if (error)
1051 goto fail;
1052
1053 nfp = VTOF(nvp);
1054
1055 if (nfp->f_flag & FN_VALID) {
1056 *vpp = nvp;
1057 goto fail;
1058 }
1059
1060 nfp->f_fflag = iep->ie_fflag;
1061 nfp->f_pnumber = iep->ie_fpnumber;
1062 nfp->f_times = iep->ie_ftimes;
1063
1064 if((nfp->f_fflag & NTFS_FFLAG_DIR) &&
1065 (nfp->f_attrtype == NTFS_A_DATA) &&
1066 (nfp->f_attrname == NULL))
1067 f_type = VDIR;
1068 else
1069 f_type = VREG;
1070
1071 nvp->v_type = f_type;
1072
1073 if ((nfp->f_attrtype == NTFS_A_DATA) &&
1074 (nfp->f_attrname == NULL))
1075 {
1076
1077 nfp->f_size = iep->ie_fsize;
1078 nfp->f_allocated = iep->ie_fallocated;
1079 nfp->f_flag |= FN_PRELOADED;
1080 } else {
1081 error = ntfs_filesize(ntmp, nfp,
1082 &nfp->f_size, &nfp->f_allocated);
1083 if (error) {
1084 vput(nvp);
1085 goto fail;
1086 }
1087 }
1088
1089 nfp->f_flag &= ~FN_VALID;
1090 *vpp = nvp;
1091 goto fail;
1092 }
1093
1094
1095 if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) {
1096 dprintf(("ntfs_ntlookupfile: diving\n"));
1097
1098 cn = *(cn_t *) (rdbuf + aoff +
1099 iep->reclen - sizeof(cn_t));
1100 rdsize = blsize;
1101
1102 error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30",
1103 ntfs_cntob(cn), rdsize, rdbuf, NULL);
1104 if (error)
1105 goto fail;
1106
1107 error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC,
1108 rdbuf, rdsize);
1109 if (error)
1110 goto fail;
1111
1112 aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize +
1113 0x18);
1114 } else if (fullscan && lookup_ctx) {
1115 cn = lookup_ctx->cn;
1116 aoff = lookup_ctx->aoff;
1117 rdsize = lookup_ctx->rdsize;
1118
1119 error = ntfs_readattr(ntmp, ip,
1120 (cn == 0) ? NTFS_A_INDXROOT : NTFS_A_INDX,
1121 "$I30", ntfs_cntob(cn), rdsize, rdbuf, NULL);
1122 if (error)
1123 goto fail;
1124
1125 if (cn != 0) {
1126 error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC,
1127 rdbuf, rdsize);
1128 if (error)
1129 goto fail;
1130 }
1131
1132 tctx = lookup_ctx;
1133 lookup_ctx = lookup_ctx->prev;
1134 FREE(tctx, M_TEMP);
1135 } else {
1136 dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n"));
1137 error = ENOENT;
1138 break;
1139 }
1140 } while (1);
1141
1142
1143 if (!fullscan && error == ENOENT) {
1144 fullscan = 1;
1145 cn = 0;
1146
1147 ddprintf(("ntfs_ntlookupfile: fullscan performed for: %.*s\n",
1148 (int) fnamelen, fname));
1149 goto loop;
1150 }
1151
1152 dprintf(("finish\n"));
1153
1154 fail:
1155 if (attrname)
1156 FREE(attrname, M_TEMP);
1157 if (lookup_ctx) {
1158 while(lookup_ctx) {
1159 tctx = lookup_ctx;
1160 lookup_ctx = lookup_ctx->prev;
1161 FREE(tctx, M_TEMP);
1162 }
1163 }
1164 ntfs_ntvattrrele(vap);
1165 #ifndef __OpenBSD__
1166 ntfs_ntput(ip);
1167 #else
1168 ntfs_ntput(ip, p);
1169 #endif
1170 free(rdbuf, M_TEMP);
1171 return (error);
1172 }
1173
1174
1175
1176
1177 int
1178 ntfs_isnamepermitted(
1179 struct ntfsmount * ntmp,
1180 struct attr_indexentry * iep)
1181 {
1182 if (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)
1183 return 1;
1184
1185 switch (iep->ie_fnametype) {
1186 case 2:
1187 ddprintf(("ntfs_isnamepermitted: skipped DOS name\n"));
1188 return 0;
1189 case 0: case 1: case 3:
1190 return 1;
1191 default:
1192 printf("ntfs_isnamepermitted: " \
1193 "WARNING! Unknown file name type: %d\n",
1194 iep->ie_fnametype);
1195 break;
1196 }
1197 return 0;
1198 }
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208 int
1209 ntfs_ntreaddir(
1210 struct ntfsmount * ntmp,
1211 struct fnode * fp,
1212 u_int32_t num,
1213 #ifndef __OpenBSD__
1214 struct attr_indexentry ** riepp)
1215 #else
1216 struct attr_indexentry ** riepp,
1217 struct proc *p)
1218 #endif
1219 {
1220 struct ntnode *ip = FTONT(fp);
1221 struct ntvattr *vap = NULL;
1222 struct ntvattr *bmvap = NULL;
1223 struct ntvattr *iavap = NULL;
1224 caddr_t rdbuf;
1225 u_int8_t *bmp = NULL;
1226 u_int32_t blsize;
1227 u_int32_t rdsize;
1228 u_int32_t attrnum;
1229 u_int32_t cpbl = 1;
1230 u_int32_t blnum;
1231 struct attr_indexentry *iep;
1232 int error = ENOENT;
1233 u_int32_t aoff, cnum;
1234
1235 dprintf(("ntfs_ntreaddir: read ino: %d, num: %d\n", ip->i_number, num));
1236 #ifndef __OpenBSD__
1237 error = ntfs_ntget(ip);
1238 #else
1239 error = ntfs_ntget(ip, p);
1240 #endif
1241 if (error)
1242 return (error);
1243
1244 error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap);
1245 if (error)
1246 return (ENOTDIR);
1247
1248 if (fp->f_dirblbuf == NULL) {
1249 fp->f_dirblsz = vap->va_a_iroot->ir_size;
1250 fp->f_dirblbuf = (caddr_t) malloc(
1251 MAX(vap->va_datalen,fp->f_dirblsz), M_NTFSDIR, M_WAITOK);
1252 }
1253
1254 blsize = fp->f_dirblsz;
1255 rdbuf = fp->f_dirblbuf;
1256
1257 dprintf(("ntfs_ntreaddir: rdbuf: %p, blsize: %d\n", rdbuf, blsize));
1258
1259 if (vap->va_a_iroot->ir_flag & NTFS_IRFLAG_INDXALLOC) {
1260 error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXBITMAP, "$I30",
1261 0, &bmvap);
1262 if (error) {
1263 error = ENOTDIR;
1264 goto fail;
1265 }
1266 bmp = (u_int8_t *) malloc(bmvap->va_datalen, M_TEMP, M_WAITOK);
1267 error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0,
1268 bmvap->va_datalen, bmp, NULL);
1269 if (error)
1270 goto fail;
1271
1272 error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDX, "$I30",
1273 0, &iavap);
1274 if (error) {
1275 error = ENOTDIR;
1276 goto fail;
1277 }
1278 cpbl = ntfs_btocn(blsize + ntfs_cntob(1) - 1);
1279 dprintf(("ntfs_ntreaddir: indexalloc: %d, cpbl: %d\n",
1280 iavap->va_datalen, cpbl));
1281 } else {
1282 dprintf(("ntfs_ntreadidir: w/o BitMap and IndexAllocation\n"));
1283 iavap = bmvap = NULL;
1284 bmp = NULL;
1285 }
1286
1287
1288 if ((fp->f_lastdnum < num) && (fp->f_lastdnum != 0)) {
1289 attrnum = fp->f_lastdattr;
1290 aoff = fp->f_lastdoff;
1291 blnum = fp->f_lastdblnum;
1292 cnum = fp->f_lastdnum;
1293 } else {
1294 attrnum = NTFS_A_INDXROOT;
1295 aoff = sizeof(struct attr_indexroot);
1296 blnum = 0;
1297 cnum = 0;
1298 }
1299
1300 do {
1301 dprintf(("ntfs_ntreaddir: scan: 0x%x, %d, %d, %d, %d\n",
1302 attrnum, (u_int32_t) blnum, cnum, num, aoff));
1303 rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize;
1304 error = ntfs_readattr(ntmp, ip, attrnum, "$I30",
1305 ntfs_cntob(blnum * cpbl), rdsize, rdbuf, NULL);
1306 if (error)
1307 goto fail;
1308
1309 if (attrnum == NTFS_A_INDX) {
1310 error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC,
1311 rdbuf, rdsize);
1312 if (error)
1313 goto fail;
1314 }
1315 if (aoff == 0)
1316 aoff = (attrnum == NTFS_A_INDX) ?
1317 (0x18 + ((struct attr_indexalloc *) rdbuf)->ia_hdrsize) :
1318 sizeof(struct attr_indexroot);
1319
1320 iep = (struct attr_indexentry *) (rdbuf + aoff);
1321 for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff);
1322 aoff += iep->reclen,
1323 iep = (struct attr_indexentry *) (rdbuf + aoff))
1324 {
1325 if (!ntfs_isnamepermitted(ntmp, iep)) continue;
1326
1327 if (cnum >= num) {
1328 fp->f_lastdnum = cnum;
1329 fp->f_lastdoff = aoff;
1330 fp->f_lastdblnum = blnum;
1331 fp->f_lastdattr = attrnum;
1332
1333 *riepp = iep;
1334
1335 error = 0;
1336 goto fail;
1337 }
1338 cnum++;
1339 }
1340
1341 if (iavap) {
1342 if (attrnum == NTFS_A_INDXROOT)
1343 blnum = 0;
1344 else
1345 blnum++;
1346
1347 while (ntfs_cntob(blnum * cpbl) < iavap->va_datalen) {
1348 if (bmp[blnum >> 3] & (1 << (blnum & 7)))
1349 break;
1350 blnum++;
1351 }
1352
1353 attrnum = NTFS_A_INDX;
1354 aoff = 0;
1355 if (ntfs_cntob(blnum * cpbl) >= iavap->va_datalen)
1356 break;
1357 dprintf(("ntfs_ntreaddir: blnum: %d\n", (u_int32_t) blnum));
1358 }
1359 } while (iavap);
1360
1361 *riepp = NULL;
1362 fp->f_lastdnum = 0;
1363
1364 fail:
1365 if (vap)
1366 ntfs_ntvattrrele(vap);
1367 if (bmvap)
1368 ntfs_ntvattrrele(bmvap);
1369 if (iavap)
1370 ntfs_ntvattrrele(iavap);
1371 if (bmp)
1372 FREE(bmp, M_TEMP);
1373 #ifndef __OpenBSD__
1374 ntfs_ntput(ip);
1375 #else
1376 ntfs_ntput(ip, p);
1377 #endif
1378 return (error);
1379 }
1380
1381
1382
1383
1384
1385 struct timespec
1386 ntfs_nttimetounix(
1387 u_int64_t nt)
1388 {
1389 struct timespec t;
1390
1391
1392 t.tv_nsec = (nt % (1000 * 1000 * 10)) * 100;
1393 t.tv_sec = nt / (1000 * 1000 * 10) -
1394 369LL * 365LL * 24LL * 60LL * 60LL -
1395 89LL * 1LL * 24LL * 60LL * 60LL;
1396 return (t);
1397 }
1398
1399 #ifndef __OpenBSD__
1400
1401
1402
1403 int
1404 ntfs_times(
1405 struct ntfsmount * ntmp,
1406 struct ntnode * ip,
1407 ntfs_times_t * tm)
1408 {
1409 struct ntvattr *vap;
1410 int error;
1411
1412 dprintf(("ntfs_times: ino: %d...\n", ip->i_number));
1413
1414 error = ntfs_ntget(ip);
1415 if (error)
1416 return (error);
1417
1418 error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap);
1419 if (error) {
1420 ntfs_ntput(ip);
1421 return (error);
1422 }
1423 *tm = vap->va_a_name->n_times;
1424 ntfs_ntvattrrele(vap);
1425 ntfs_ntput(ip);
1426
1427 return (0);
1428 }
1429 #endif
1430
1431
1432
1433
1434
1435
1436 int
1437 ntfs_filesize(
1438 struct ntfsmount * ntmp,
1439 struct fnode * fp,
1440 u_int64_t * size,
1441 u_int64_t * bytes)
1442 {
1443 struct ntvattr *vap;
1444 struct ntnode *ip = FTONT(fp);
1445 u_int64_t sz, bn;
1446 int error;
1447
1448 dprintf(("ntfs_filesize: ino: %d\n", ip->i_number));
1449
1450 error = ntfs_ntvattrget(ntmp, ip,
1451 fp->f_attrtype, fp->f_attrname, 0, &vap);
1452 if (error)
1453 return (error);
1454
1455 bn = vap->va_allocated;
1456 sz = vap->va_datalen;
1457
1458 dprintf(("ntfs_filesize: %d bytes (%d bytes allocated)\n",
1459 (u_int32_t) sz, (u_int32_t) bn));
1460
1461 if (size)
1462 *size = sz;
1463 if (bytes)
1464 *bytes = bn;
1465
1466 ntfs_ntvattrrele(vap);
1467
1468 return (0);
1469 }
1470
1471
1472
1473
1474 int
1475 ntfs_writeattr_plain(
1476 struct ntfsmount * ntmp,
1477 struct ntnode * ip,
1478 u_int32_t attrnum,
1479 char *attrname,
1480 off_t roff,
1481 size_t rsize,
1482 void *rdata,
1483 size_t * initp,
1484 struct uio *uio)
1485 {
1486 size_t init;
1487 int error = 0;
1488 off_t off = roff, left = rsize, towrite;
1489 caddr_t data = rdata;
1490 struct ntvattr *vap;
1491 *initp = 0;
1492
1493 while (left) {
1494 error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname,
1495 ntfs_btocn(off), &vap);
1496 if (error)
1497 return (error);
1498 towrite = MIN(left, ntfs_cntob(vap->va_vcnend + 1) - off);
1499 ddprintf(("ntfs_writeattr_plain: o: %d, s: %d (%d - %d)\n",
1500 (u_int32_t) off, (u_int32_t) towrite,
1501 (u_int32_t) vap->va_vcnstart,
1502 (u_int32_t) vap->va_vcnend));
1503 error = ntfs_writentvattr_plain(ntmp, ip, vap,
1504 off - ntfs_cntob(vap->va_vcnstart),
1505 towrite, data, &init, uio);
1506 if (error) {
1507 dprintf(("ntfs_writeattr_plain: " \
1508 "ntfs_writentvattr_plain failed: o: %d, s: %d\n",
1509 (u_int32_t) off, (u_int32_t) towrite));
1510 dprintf(("ntfs_writeattr_plain: attrib: %d - %d\n",
1511 (u_int32_t) vap->va_vcnstart,
1512 (u_int32_t) vap->va_vcnend));
1513 ntfs_ntvattrrele(vap);
1514 break;
1515 }
1516 ntfs_ntvattrrele(vap);
1517 left -= towrite;
1518 off += towrite;
1519 data = data + towrite;
1520 *initp += init;
1521 }
1522
1523 return (error);
1524 }
1525
1526
1527
1528
1529
1530
1531 int
1532 ntfs_writentvattr_plain(
1533 struct ntfsmount * ntmp,
1534 struct ntnode * ip,
1535 struct ntvattr * vap,
1536 off_t roff,
1537 size_t rsize,
1538 void *rdata,
1539 size_t * initp,
1540 struct uio *uio)
1541 {
1542 int error = 0;
1543 int off;
1544 int cnt;
1545 cn_t ccn, ccl, cn, left, cl;
1546 caddr_t data = rdata;
1547 struct buf *bp;
1548 size_t tocopy;
1549
1550 *initp = 0;
1551
1552 if ((vap->va_flag & NTFS_AF_INRUN) == 0) {
1553 dprintf(("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n"));
1554 return ENOTTY;
1555 }
1556
1557 ddprintf(("ntfs_writentvattr_plain: data in run: %lu chains\n",
1558 vap->va_vruncnt));
1559
1560 off = roff;
1561 left = rsize;
1562 ccl = 0;
1563 ccn = 0;
1564 cnt = 0;
1565 for (; left && (cnt < vap->va_vruncnt); cnt++) {
1566 ccn = vap->va_vruncn[cnt];
1567 ccl = vap->va_vruncl[cnt];
1568
1569 ddprintf(("ntfs_writentvattr_plain: " \
1570 "left %d, cn: 0x%x, cl: %d, off: %d\n", \
1571 (u_int32_t) left, (u_int32_t) ccn, \
1572 (u_int32_t) ccl, (u_int32_t) off));
1573
1574 if (ntfs_cntob(ccl) < off) {
1575 off -= ntfs_cntob(ccl);
1576 cnt++;
1577 continue;
1578 }
1579 if (!ccn && ip->i_number != NTFS_BOOTINO)
1580 continue;
1581
1582 ccl -= ntfs_btocn(off);
1583 cn = ccn + ntfs_btocn(off);
1584 off = ntfs_btocnoff(off);
1585
1586 while (left && ccl) {
1587
1588
1589
1590
1591
1592
1593 tocopy = MIN(left, ntfs_cntob(1) - off);
1594 cl = ntfs_btocl(tocopy + off);
1595 KASSERT(cl == 1 && tocopy <= ntfs_cntob(1));
1596 ddprintf(("ntfs_writentvattr_plain: write: " \
1597 "cn: 0x%x cl: %d, off: %d len: %d, left: %d\n",
1598 (u_int32_t) cn, (u_int32_t) cl,
1599 (u_int32_t) off, (u_int32_t) tocopy,
1600 (u_int32_t) left));
1601 if ((off == 0) && (tocopy == ntfs_cntob(cl)))
1602 {
1603 bp = getblk(ntmp->ntm_devvp, ntfs_cntobn(cn),
1604 ntfs_cntob(cl), 0, 0);
1605 clrbuf(bp);
1606 } else {
1607 error = bread(ntmp->ntm_devvp, ntfs_cntobn(cn),
1608 ntfs_cntob(cl), NOCRED, &bp);
1609 if (error) {
1610 brelse(bp);
1611 return (error);
1612 }
1613 }
1614 if (uio)
1615 uiomove(bp->b_data + off, tocopy, uio);
1616 else
1617 memcpy(bp->b_data + off, data, tocopy);
1618 bawrite(bp);
1619 data = data + tocopy;
1620 *initp += tocopy;
1621 off = 0;
1622 left -= tocopy;
1623 cn += cl;
1624 ccl -= cl;
1625 }
1626 }
1627
1628 if (left) {
1629 printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n");
1630 error = EINVAL;
1631 }
1632
1633 return (error);
1634 }
1635
1636
1637
1638
1639
1640
1641 int
1642 ntfs_readntvattr_plain(
1643 struct ntfsmount * ntmp,
1644 struct ntnode * ip,
1645 struct ntvattr * vap,
1646 off_t roff,
1647 size_t rsize,
1648 void *rdata,
1649 size_t * initp,
1650 struct uio *uio)
1651 {
1652 int error = 0;
1653 int off;
1654
1655 *initp = 0;
1656 if (vap->va_flag & NTFS_AF_INRUN) {
1657 int cnt;
1658 cn_t ccn, ccl, cn, left, cl;
1659 caddr_t data = rdata;
1660 struct buf *bp;
1661 size_t tocopy;
1662
1663 ddprintf(("ntfs_readntvattr_plain: data in run: %lu chains\n",
1664 vap->va_vruncnt));
1665
1666 off = roff;
1667 left = rsize;
1668 ccl = 0;
1669 ccn = 0;
1670 cnt = 0;
1671 while (left && (cnt < vap->va_vruncnt)) {
1672 ccn = vap->va_vruncn[cnt];
1673 ccl = vap->va_vruncl[cnt];
1674
1675 ddprintf(("ntfs_readntvattr_plain: " \
1676 "left %d, cn: 0x%x, cl: %d, off: %d\n", \
1677 (u_int32_t) left, (u_int32_t) ccn, \
1678 (u_int32_t) ccl, (u_int32_t) off));
1679
1680 if (ntfs_cntob(ccl) < off) {
1681 off -= ntfs_cntob(ccl);
1682 cnt++;
1683 continue;
1684 }
1685 if (ccn || ip->i_number == NTFS_BOOTINO) {
1686 ccl -= ntfs_btocn(off);
1687 cn = ccn + ntfs_btocn(off);
1688 off = ntfs_btocnoff(off);
1689
1690 while (left && ccl) {
1691
1692
1693
1694
1695
1696
1697
1698 tocopy = MIN(left,
1699 ntfs_cntob(1) - off);
1700 cl = ntfs_btocl(tocopy + off);
1701 KASSERT(cl == 1 &&
1702 tocopy <= ntfs_cntob(1));
1703
1704 ddprintf(("ntfs_readntvattr_plain: " \
1705 "read: cn: 0x%x cl: %d, " \
1706 "off: %d len: %d, left: %d\n",
1707 (u_int32_t) cn,
1708 (u_int32_t) cl,
1709 (u_int32_t) off,
1710 (u_int32_t) tocopy,
1711 (u_int32_t) left));
1712 error = bread(ntmp->ntm_devvp,
1713 ntfs_cntobn(cn),
1714 ntfs_cntob(cl),
1715 NOCRED, &bp);
1716 if (error) {
1717 brelse(bp);
1718 return (error);
1719 }
1720 if (uio) {
1721 uiomove(bp->b_data + off,
1722 tocopy, uio);
1723 } else {
1724 memcpy(data, bp->b_data + off,
1725 tocopy);
1726 }
1727 brelse(bp);
1728 data = data + tocopy;
1729 *initp += tocopy;
1730 off = 0;
1731 left -= tocopy;
1732 cn += cl;
1733 ccl -= cl;
1734 }
1735 } else {
1736 tocopy = MIN(left, ntfs_cntob(ccl) - off);
1737 ddprintf(("ntfs_readntvattr_plain: "
1738 "hole: ccn: 0x%x ccl: %d, off: %d, " \
1739 " len: %d, left: %d\n",
1740 (u_int32_t) ccn, (u_int32_t) ccl,
1741 (u_int32_t) off, (u_int32_t) tocopy,
1742 (u_int32_t) left));
1743 left -= tocopy;
1744 off = 0;
1745 if (uio) {
1746 size_t remains = tocopy;
1747 for(; remains; remains--)
1748 uiomove("", 1, uio);
1749 } else
1750 bzero(data, tocopy);
1751 data = data + tocopy;
1752 }
1753 cnt++;
1754 }
1755 if (left) {
1756 printf("ntfs_readntvattr_plain: POSSIBLE RUN ERROR\n");
1757 error = E2BIG;
1758 }
1759 } else {
1760 ddprintf(("ntfs_readnvattr_plain: data is in mft record\n"));
1761 if (uio)
1762 uiomove(vap->va_datap + roff, rsize, uio);
1763 else
1764 memcpy(rdata, vap->va_datap + roff, rsize);
1765 *initp += rsize;
1766 }
1767
1768 return (error);
1769 }
1770
1771
1772
1773
1774 int
1775 ntfs_readattr_plain(
1776 struct ntfsmount * ntmp,
1777 struct ntnode * ip,
1778 u_int32_t attrnum,
1779 char *attrname,
1780 off_t roff,
1781 size_t rsize,
1782 void *rdata,
1783 size_t * initp,
1784 struct uio *uio)
1785 {
1786 size_t init;
1787 int error = 0;
1788 off_t off = roff, left = rsize, toread;
1789 caddr_t data = rdata;
1790 struct ntvattr *vap;
1791 *initp = 0;
1792
1793 while (left) {
1794 error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname,
1795 ntfs_btocn(off), &vap);
1796 if (error)
1797 return (error);
1798 toread = MIN(left, ntfs_cntob(vap->va_vcnend + 1) - off);
1799 ddprintf(("ntfs_readattr_plain: o: %d, s: %d (%d - %d)\n",
1800 (u_int32_t) off, (u_int32_t) toread,
1801 (u_int32_t) vap->va_vcnstart,
1802 (u_int32_t) vap->va_vcnend));
1803 error = ntfs_readntvattr_plain(ntmp, ip, vap,
1804 off - ntfs_cntob(vap->va_vcnstart),
1805 toread, data, &init, uio);
1806 if (error) {
1807 printf("ntfs_readattr_plain: " \
1808 "ntfs_readntvattr_plain failed: o: %d, s: %d\n",
1809 (u_int32_t) off, (u_int32_t) toread);
1810 printf("ntfs_readattr_plain: attrib: %d - %d\n",
1811 (u_int32_t) vap->va_vcnstart,
1812 (u_int32_t) vap->va_vcnend);
1813 ntfs_ntvattrrele(vap);
1814 break;
1815 }
1816 ntfs_ntvattrrele(vap);
1817 left -= toread;
1818 off += toread;
1819 data = data + toread;
1820 *initp += init;
1821 }
1822
1823 return (error);
1824 }
1825
1826
1827
1828
1829 int
1830 ntfs_readattr(
1831 struct ntfsmount * ntmp,
1832 struct ntnode * ip,
1833 u_int32_t attrnum,
1834 char *attrname,
1835 off_t roff,
1836 size_t rsize,
1837 void *rdata,
1838 struct uio *uio)
1839 {
1840 int error = 0;
1841 struct ntvattr *vap;
1842 size_t init;
1843
1844 ddprintf(("ntfs_readattr: reading %d: 0x%x, from %d size %d bytes\n",
1845 ip->i_number, attrnum, (u_int32_t) roff, (u_int32_t) rsize));
1846
1847 error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 0, &vap);
1848 if (error)
1849 return (error);
1850
1851 if ((roff > vap->va_datalen) ||
1852 (roff + rsize > vap->va_datalen)) {
1853 printf("ntfs_readattr: offset too big: %ld (%ld) > %ld\n",
1854 (long int) roff, (long int) roff + rsize,
1855 (long int) vap->va_datalen);
1856 ntfs_ntvattrrele(vap);
1857 return (E2BIG);
1858 }
1859 if (vap->va_compression && vap->va_compressalg) {
1860 u_int8_t *cup;
1861 u_int8_t *uup;
1862 off_t off = roff, left = rsize, tocopy;
1863 caddr_t data = rdata;
1864 cn_t cn;
1865
1866 ddprintf(("ntfs_ntreadattr: compression: %d\n",
1867 vap->va_compressalg));
1868
1869 MALLOC(cup, u_int8_t *, ntfs_cntob(NTFS_COMPUNIT_CL),
1870 M_NTFSDECOMP, M_WAITOK);
1871 MALLOC(uup, u_int8_t *, ntfs_cntob(NTFS_COMPUNIT_CL),
1872 M_NTFSDECOMP, M_WAITOK);
1873
1874 cn = (ntfs_btocn(roff)) & (~(NTFS_COMPUNIT_CL - 1));
1875 off = roff - ntfs_cntob(cn);
1876
1877 while (left) {
1878 error = ntfs_readattr_plain(ntmp, ip, attrnum,
1879 attrname, ntfs_cntob(cn),
1880 ntfs_cntob(NTFS_COMPUNIT_CL),
1881 cup, &init, NULL);
1882 if (error)
1883 break;
1884
1885 tocopy = MIN(left, ntfs_cntob(NTFS_COMPUNIT_CL) - off);
1886
1887 if (init == ntfs_cntob(NTFS_COMPUNIT_CL)) {
1888 if (uio)
1889 uiomove(cup + off, tocopy, uio);
1890 else
1891 memcpy(data, cup + off, tocopy);
1892 } else if (init == 0) {
1893 if (uio) {
1894 size_t remains = tocopy;
1895 for(; remains; remains--)
1896 uiomove("", 1, uio);
1897 }
1898 else
1899 bzero(data, tocopy);
1900 } else {
1901 error = ntfs_uncompunit(ntmp, uup, cup);
1902 if (error)
1903 break;
1904 if (uio)
1905 uiomove(uup + off, tocopy, uio);
1906 else
1907 memcpy(data, uup + off, tocopy);
1908 }
1909
1910 left -= tocopy;
1911 data = data + tocopy;
1912 off += tocopy - ntfs_cntob(NTFS_COMPUNIT_CL);
1913 cn += NTFS_COMPUNIT_CL;
1914 }
1915
1916 FREE(uup, M_NTFSDECOMP);
1917 FREE(cup, M_NTFSDECOMP);
1918 } else
1919 error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname,
1920 roff, rsize, rdata, &init, uio);
1921 ntfs_ntvattrrele(vap);
1922 return (error);
1923 }
1924
1925 #if UNUSED_CODE
1926 int
1927 ntfs_parserun(
1928 cn_t * cn,
1929 cn_t * cl,
1930 u_int8_t * run,
1931 u_long len,
1932 u_long *off)
1933 {
1934 u_int8_t sz;
1935 int i;
1936
1937 if (NULL == run) {
1938 printf("ntfs_parsetun: run == NULL\n");
1939 return (EINVAL);
1940 }
1941 sz = run[(*off)++];
1942 if (0 == sz) {
1943 printf("ntfs_parserun: trying to go out of run\n");
1944 return (E2BIG);
1945 }
1946 *cl = 0;
1947 if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) {
1948 printf("ntfs_parserun: " \
1949 "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n",
1950 sz, len, *off);
1951 return (EINVAL);
1952 }
1953 for (i = 0; i < (sz & 0xF); i++)
1954 *cl += (u_int32_t) run[(*off)++] << (i << 3);
1955
1956 sz >>= 4;
1957 if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) {
1958 printf("ntfs_parserun: " \
1959 "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n",
1960 sz, len, *off);
1961 return (EINVAL);
1962 }
1963 for (i = 0; i < (sz & 0xF); i++)
1964 *cn += (u_int32_t) run[(*off)++] << (i << 3);
1965
1966 return (0);
1967 }
1968 #endif
1969
1970
1971
1972
1973 int
1974 ntfs_procfixups(
1975 struct ntfsmount * ntmp,
1976 u_int32_t magic,
1977 caddr_t buf,
1978 size_t len)
1979 {
1980 struct fixuphdr *fhp = (struct fixuphdr *) buf;
1981 int i;
1982 u_int16_t fixup;
1983 u_int16_t *fxp;
1984 u_int16_t *cfxp;
1985
1986 if (fhp->fh_magic != magic) {
1987 printf("ntfs_procfixups: magic doesn't match: %08x != %08x\n",
1988 fhp->fh_magic, magic);
1989 return (EINVAL);
1990 }
1991 if ((fhp->fh_fnum - 1) * ntmp->ntm_bps != len) {
1992 printf("ntfs_procfixups: " \
1993 "bad fixups number: %d for %ld bytes block\n",
1994 fhp->fh_fnum, (long)len);
1995 return (EINVAL);
1996 }
1997 if (fhp->fh_foff >= ntmp->ntm_spc * ntmp->ntm_mftrecsz * ntmp->ntm_bps) {
1998 printf("ntfs_procfixups: invalid offset: %x", fhp->fh_foff);
1999 return (EINVAL);
2000 }
2001 fxp = (u_int16_t *) (buf + fhp->fh_foff);
2002 cfxp = (u_int16_t *) (buf + ntmp->ntm_bps - 2);
2003 fixup = *fxp++;
2004 for (i = 1; i < fhp->fh_fnum; i++, fxp++) {
2005 if (*cfxp != fixup) {
2006 printf("ntfs_procfixups: fixup %d doesn't match\n", i);
2007 return (EINVAL);
2008 }
2009 *cfxp = *fxp;
2010 cfxp = (u_int16_t *)((caddr_t)cfxp + ntmp->ntm_bps);
2011 }
2012 return (0);
2013 }
2014
2015 #if UNUSED_CODE
2016 int
2017 ntfs_runtocn(
2018 cn_t * cn,
2019 struct ntfsmount * ntmp,
2020 u_int8_t * run,
2021 u_long len,
2022 cn_t vcn)
2023 {
2024 cn_t ccn = 0;
2025 cn_t ccl = 0;
2026 u_long off = 0;
2027 int error = 0;
2028
2029 #if NTFS_DEBUG
2030 int i;
2031 printf("ntfs_runtocn: run: %p, %ld bytes, vcn:%ld\n",
2032 run, len, (u_long) vcn);
2033 printf("ntfs_runtocn: run: ");
2034 for (i = 0; i < len; i++)
2035 printf("0x%02x ", run[i]);
2036 printf("\n");
2037 #endif
2038
2039 if (NULL == run) {
2040 printf("ntfs_runtocn: run == NULL\n");
2041 return (EINVAL);
2042 }
2043 do {
2044 if (run[off] == 0) {
2045 printf("ntfs_runtocn: vcn too big\n");
2046 return (E2BIG);
2047 }
2048 vcn -= ccl;
2049 error = ntfs_parserun(&ccn, &ccl, run, len, &off);
2050 if (error) {
2051 printf("ntfs_runtocn: ntfs_parserun failed\n");
2052 return (error);
2053 }
2054 } while (ccl <= vcn);
2055 *cn = ccn + vcn;
2056 return (0);
2057 }
2058 #endif
2059
2060
2061
2062
2063
2064 void
2065 ntfs_toupper_init()
2066 {
2067 ntfs_toupper_tab = (wchar *) NULL;
2068 lockinit(&ntfs_toupper_lock, PVFS, "ntfs_toupper", 0, 0);
2069 ntfs_toupper_usecount = 0;
2070 }
2071
2072
2073
2074
2075
2076 int
2077 #ifndef __OpenBSD__
2078 ntfs_toupper_use(mp, ntmp)
2079 struct mount *mp;
2080 struct ntfsmount *ntmp;
2081 #else
2082 ntfs_toupper_use(mp, ntmp, p)
2083 struct mount *mp;
2084 struct ntfsmount *ntmp;
2085 struct proc *p;
2086 #endif
2087 {
2088 int error = 0;
2089 struct vnode *vp;
2090
2091
2092 lockmgr(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL);
2093
2094
2095
2096 if (ntfs_toupper_tab)
2097 goto out;
2098
2099
2100
2101
2102
2103
2104 MALLOC(ntfs_toupper_tab, wchar *, 256 * 256 * sizeof(wchar),
2105 M_NTFSRDATA, M_WAITOK);
2106
2107 if ((error = VFS_VGET(mp, NTFS_UPCASEINO, &vp)))
2108 goto out;
2109 error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
2110 0, 256*256*sizeof(wchar), (char *) ntfs_toupper_tab,
2111 NULL);
2112 vput(vp);
2113
2114 out:
2115 ntfs_toupper_usecount++;
2116 lockmgr(&ntfs_toupper_lock, LK_RELEASE, NULL);
2117 return (error);
2118 }
2119
2120
2121
2122
2123
2124 void
2125 #ifndef __OpenBSD__
2126 ntfs_toupper_unuse()
2127 #else
2128 ntfs_toupper_unuse(p)
2129 struct proc *p;
2130 #endif
2131 {
2132
2133 lockmgr(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL);
2134
2135 ntfs_toupper_usecount--;
2136 if (ntfs_toupper_usecount == 0) {
2137 FREE(ntfs_toupper_tab, M_NTFSRDATA);
2138 ntfs_toupper_tab = NULL;
2139 }
2140 #ifdef DIAGNOSTIC
2141 else if (ntfs_toupper_usecount < 0) {
2142 panic("ntfs_toupper_unuse(): use count negative: %d",
2143 ntfs_toupper_usecount);
2144 }
2145 #endif
2146
2147
2148 lockmgr(&ntfs_toupper_lock, LK_RELEASE, NULL);
2149 }