(index<- ) ./libstd/path.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12
13 Cross-platform file path handling
14
15 */
16
17 #[allow(missing_doc)];
18
19 use c_str::ToCStr;
20 use c_str;
21 use clone::Clone;
22 use cmp::Eq;
23 use container::Container;
24 use iter::{Iterator, range};
25 use libc;
26 use num;
27 use option::{None, Option, Some};
28 use str::{OwnedStr, Str, StrSlice, StrVector};
29 use to_str::ToStr;
30 use ascii::{AsciiCast, AsciiStr};
31 use vec::{Vector, OwnedVector, ImmutableVector, OwnedCopyableVector};
32
33 #[cfg(windows)]
34 pub use Path = self::WindowsPath;
35 #[cfg(unix)]
36 pub use Path = self::PosixPath;
37
38 #[deriving(Clone, Eq)]
39 pub struct WindowsPath {
40 host: Option<~str>,
41 device: Option<~str>,
42 is_absolute: bool,
43 components: ~[~str],
44 }
45
46 pub fn WindowsPath(s: &str) -> WindowsPath {
47 GenericPath::from_str(s)
48 }
49
50 #[deriving(Clone, Eq)]
51 pub struct PosixPath {
52 is_absolute: bool,
53 components: ~[~str],
54 }
55
56 pub fn PosixPath(s: &str) -> PosixPath {
57 GenericPath::from_str(s)
58 }
59
60 pub trait GenericPath : Clone + Eq + ToStr {
61 /// Converts a string to a path.
62 fn from_str(&str) -> Self;
63
64 /// Returns the directory component of `self`, as a string.
65 fn dirname(&self) -> ~str {
66 let s = self.dir_path().to_str();
67 match s.len() {
68 0 => ~".",
69 _ => s,
70 }
71 }
72
73 /// Returns the file component of `self`, as a string option.
74 /// Returns None if `self` names a directory.
75 fn filename<'a>(&'a self) -> Option<&'a str> {
76 match self.components().len() {
77 0 => None,
78 n => Some(self.components()[n - 1].as_slice()),
79 }
80 }
81
82 /// Returns the stem of the file component of `self`, as a string option.
83 /// The stem is the slice of a filename starting at 0 and ending just before
84 /// the last '.' in the name.
85 /// Returns None if `self` names a directory.
86 fn filestem<'a>(&'a self) -> Option<&'a str> {
87 match self.filename() {
88 None => None,
89 Some(ref f) => {
90 match f.rfind('.') {
91 Some(p) => Some(f.slice_to(p)),
92 None => Some((*f)),
93 }
94 }
95 }
96 }
97
98 /// Returns the type of the file component of `self`, as a string option.
99 /// The file type is the slice of a filename starting just after the last
100 /// '.' in the name and ending at the last index in the filename.
101 /// Returns None if `self` names a directory.
102 fn filetype<'a>(&'a self) -> Option<&'a str> {
103 match self.filename() {
104 None => None,
105 Some(ref f) => {
106 match f.rfind('.') {
107 Some(p) if p < f.len() => Some(f.slice_from(p)),
108 _ => None,
109 }
110 }
111 }
112 }
113
114 /// Returns a new path consisting of `self` with the parent directory component replaced
115 /// with the given string.
116 fn with_dirname(&self, (&str)) -> Self;
117
118 /// Returns a new path consisting of `self` with the file component replaced
119 /// with the given string.
120 fn with_filename(&self, (&str)) -> Self;
121
122 /// Returns a new path consisting of `self` with the file stem replaced
123 /// with the given string.
124 fn with_filestem(&self, s: &str) -> Self {
125 match self.filetype() {
126 None => self.with_filename(s),
127 Some(ref t) => self.with_filename(s.to_owned() + *t),
128 }
129 }
130
131 /// Returns a new path consisting of `self` with the file type replaced
132 /// with the given string.
133 fn with_filetype(&self, t: &str) -> Self {
134 match (t.len(), self.filestem()) {
135 (0, None) => (*self).clone(),
136 (0, Some(ref s)) => self.with_filename(*s),
137 (_, None) => self.with_filename(fmt!(".%s", t)),
138 (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)),
139 }
140 }
141
142 /// Returns the directory component of `self`, as a new path.
143 /// If `self` has no parent, returns `self`.
144 fn dir_path(&self) -> Self {
145 match self.components().len() {
146 0 => (*self).clone(),
147 _ => self.pop(),
148 }
149 }
150
151 /// Returns the file component of `self`, as a new path.
152 /// If `self` names a directory, returns the empty path.
153 fn file_path(&self) -> Self;
154
155 /// Returns a new path whose parent directory is `self` and whose
156 /// file component is the given string.
157 fn push(&self, (&str)) -> Self;
158
159 /// Returns a new path consisting of the given path, made relative to `self`.
160 fn push_rel(&self, other: &Self) -> Self {
161 assert!(!other.is_absolute());
162 self.push_many(other.components())
163 }
164
165 /// Returns a new path consisting of the path given by the given vector
166 /// of strings, relative to `self`.
167 fn push_many<S: Str>(&self, (&[S])) -> Self;
168
169 /// Identical to `dir_path` except in the case where `self` has only one
170 /// component. In this case, `pop` returns the empty path.
171 fn pop(&self) -> Self;
172
173 /// The same as `push_rel`, except that the directory argument must not
174 /// contain directory separators in any of its components.
175 fn unsafe_join(&self, (&Self)) -> Self;
176
177 /// On Unix, always returns `false`. On Windows, returns `true` iff `self`'s
178 /// file stem is one of: `con` `aux` `com1` `com2` `com3` `com4`
179 /// `lpt1` `lpt2` `lpt3` `prn` `nul`.
180 fn is_restricted(&self) -> bool;
181
182 /// Returns a new path that names the same file as `self`, without containing
183 /// any '.', '..', or empty components. On Windows, uppercases the drive letter
184 /// as well.
185 fn normalize(&self) -> Self;
186
187 /// Returns `true` if `self` is an absolute path.
188 fn is_absolute(&self) -> bool;
189
190 /// True if `self` is an ancestor of `other`.
191 // See `test_is_ancestor_of` for examples.
192 fn is_ancestor_of(&self, other: &Self) -> bool {
193 debug!("%s / %s %? %?", self.to_str(), other.to_str(), self.is_absolute(),
194 self.components().len());
195 self == other ||
196 (!other.components().is_empty() &&
197 !(self.components().is_empty() && !self.is_absolute()) &&
198 self.is_ancestor_of(&other.pop()))
199 }
200
201 /// Finds the relative path from one file to another.
202 fn get_relative_to(&self, abs2: (&Self)) -> Self {
203 assert!(self.is_absolute());
204 assert!(abs2.is_absolute());
205 let abs1 = self.normalize();
206 let abs2 = abs2.normalize();
207
208 let split1: &[~str] = abs1.components();
209 let split2: &[~str] = abs2.components();
210 let len1 = split1.len();
211 let len2 = split2.len();
212 assert!(len1 > 0);
213 assert!(len2 > 0);
214
215 let max_common_path = num::min(len1, len2) - 1;
216 let mut start_idx = 0;
217 while start_idx < max_common_path
218 && split1[start_idx] == split2[start_idx] {
219 start_idx += 1;
220 }
221
222 let mut path: ~[~str] = ~[];
223 for _ in range(start_idx, len1 - 1) { path.push(~".."); };
224
225 path.push_all(split2.slice(start_idx, len2 - 1));
226
227 let mut result: Self = GenericPath::from_str(".");
228 if !path.is_empty() {
229 // Without this type hint, the typechecker doesn't seem to like it
230 let p: Self = GenericPath::from_str("");
231 result = p.push_many(path);
232 };
233 result
234 }
235
236 fn components<'a>(&'a self) -> &'a [~str];
237 }
238
239 #[cfg(target_os = "linux")]
240 #[cfg(target_os = "android")]
241 mod stat {
242 #[cfg(target_arch = "x86")]
243 pub mod arch {
244 use libc;
245
246 pub fn default_stat() -> libc::stat {
247 libc::stat {
248 st_dev: 0,
249 __pad1: 0,
250 st_ino: 0,
251 st_mode: 0,
252 st_nlink: 0,
253 st_uid: 0,
254 st_gid: 0,
255 st_rdev: 0,
256 __pad2: 0,
257 st_size: 0,
258 st_blksize: 0,
259 st_blocks: 0,
260 st_atime: 0,
261 st_atime_nsec: 0,
262 st_mtime: 0,
263 st_mtime_nsec: 0,
264 st_ctime: 0,
265 st_ctime_nsec: 0,
266 __unused4: 0,
267 __unused5: 0,
268 }
269 }
270 }
271
272 #[cfg(target_arch = "arm")]
273 pub mod arch {
274 use libc;
275
276 pub fn default_stat() -> libc::stat {
277 libc::stat {
278 st_dev: 0,
279 __pad0: [0, ..4],
280 __st_ino: 0,
281 st_mode: 0,
282 st_nlink: 0,
283 st_uid: 0,
284 st_gid: 0,
285 st_rdev: 0,
286 __pad3: [0, ..4],
287 st_size: 0,
288 st_blksize: 0,
289 st_blocks: 0,
290 st_atime: 0,
291 st_atime_nsec: 0,
292 st_mtime: 0,
293 st_mtime_nsec: 0,
294 st_ctime: 0,
295 st_ctime_nsec: 0,
296 st_ino: 0
297 }
298 }
299 }
300
301 #[cfg(target_arch = "mips")]
302 pub mod arch {
303 use libc;
304
305 pub fn default_stat() -> libc::stat {
306 libc::stat {
307 st_dev: 0,
308 st_pad1: [0, ..3],
309 st_ino: 0,
310 st_mode: 0,
311 st_nlink: 0,
312 st_uid: 0,
313 st_gid: 0,
314 st_rdev: 0,
315 st_pad2: [0, ..2],
316 st_size: 0,
317 st_pad3: 0,
318 st_atime: 0,
319 st_atime_nsec: 0,
320 st_mtime: 0,
321 st_mtime_nsec: 0,
322 st_ctime: 0,
323 st_ctime_nsec: 0,
324 st_blksize: 0,
325 st_blocks: 0,
326 st_pad5: [0, ..14],
327 }
328 }
329 }
330
331 #[cfg(target_arch = "x86_64")]
332 pub mod arch {
333 use libc;
334
335 pub fn default_stat() -> libc::stat {
336 libc::stat {
337 st_dev: 0,
338 st_ino: 0,
339 st_nlink: 0,
340 st_mode: 0,
341 st_uid: 0,
342 st_gid: 0,
343 __pad0: 0,
344 st_rdev: 0,
345 st_size: 0,
346 st_blksize: 0,
347 st_blocks: 0,
348 st_atime: 0,
349 st_atime_nsec: 0,
350 st_mtime: 0,
351 st_mtime_nsec: 0,
352 st_ctime: 0,
353 st_ctime_nsec: 0,
354 __unused: [0, 0, 0],
355 }
356 }
357 }
358 }
359
360 #[cfg(target_os = "freebsd")]
361 mod stat {
362 #[cfg(target_arch = "x86_64")]
363 pub mod arch {
364 use libc;
365
366 pub fn default_stat() -> libc::stat {
367 libc::stat {
368 st_dev: 0,
369 st_ino: 0,
370 st_mode: 0,
371 st_nlink: 0,
372 st_uid: 0,
373 st_gid: 0,
374 st_rdev: 0,
375 st_atime: 0,
376 st_atime_nsec: 0,
377 st_mtime: 0,
378 st_mtime_nsec: 0,
379 st_ctime: 0,
380 st_ctime_nsec: 0,
381 st_size: 0,
382 st_blocks: 0,
383 st_blksize: 0,
384 st_flags: 0,
385 st_gen: 0,
386 st_lspare: 0,
387 st_birthtime: 0,
388 st_birthtime_nsec: 0,
389 __unused: [0, 0],
390 }
391 }
392 }
393 }
394
395 #[cfg(target_os = "macos")]
396 mod stat {
397 pub mod arch {
398 use libc;
399
400 pub fn default_stat() -> libc::stat {
401 libc::stat {
402 st_dev: 0,
403 st_mode: 0,
404 st_nlink: 0,
405 st_ino: 0,
406 st_uid: 0,
407 st_gid: 0,
408 st_rdev: 0,
409 st_atime: 0,
410 st_atime_nsec: 0,
411 st_mtime: 0,
412 st_mtime_nsec: 0,
413 st_ctime: 0,
414 st_ctime_nsec: 0,
415 st_birthtime: 0,
416 st_birthtime_nsec: 0,
417 st_size: 0,
418 st_blocks: 0,
419 st_blksize: 0,
420 st_flags: 0,
421 st_gen: 0,
422 st_lspare: 0,
423 st_qspare: [0, 0],
424 }
425 }
426 }
427 }
428
429 #[cfg(target_os = "win32")]
430 mod stat {
431 pub mod arch {
432 use libc;
433 pub fn default_stat() -> libc::stat {
434 libc::stat {
435 st_dev: 0,
436 st_ino: 0,
437 st_mode: 0,
438 st_nlink: 0,
439 st_uid: 0,
440 st_gid: 0,
441 st_rdev: 0,
442 st_size: 0,
443 st_atime: 0,
444 st_mtime: 0,
445 st_ctime: 0,
446 }
447 }
448 }
449 }
450
451 #[cfg(target_os = "win32")]
452 impl WindowsPath {
453 pub fn stat(&self) -> Option<libc::stat> {
454 #[fixed_stack_segment]; #[inline(never)];
455 do self.with_c_str |buf| {
456 let mut st = stat::arch::default_stat();
457 match unsafe { libc::stat(buf, &mut st) } {
458 0 => Some(st),
459 _ => None,
460 }
461 }
462 }
463
464 pub fn exists(&self) -> bool {
465 match self.stat() {
466 None => false,
467 Some(_) => true,
468 }
469 }
470
471 pub fn get_size(&self) -> Option<i64> {
472 match self.stat() {
473 None => None,
474 Some(ref st) => Some(st.st_size as i64),
475 }
476 }
477
478 pub fn get_mode(&self) -> Option<uint> {
479 match self.stat() {
480 None => None,
481 Some(ref st) => Some(st.st_mode as uint),
482 }
483 }
484 }
485
486 #[cfg(not(target_os = "win32"))]
487 impl PosixPath {
488 pub fn stat(&self) -> Option<libc::stat> {
489 #[fixed_stack_segment]; #[inline(never)];
490 do self.with_c_str |buf| {
491 let mut st = stat::arch::default_stat();
492 match unsafe { libc::stat(buf as *libc::c_char, &mut st) } {
493 0 => Some(st),
494 _ => None,
495 }
496 }
497 }
498
499 pub fn exists(&self) -> bool {
500 match self.stat() {
501 None => false,
502 Some(_) => true,
503 }
504 }
505
506 pub fn get_size(&self) -> Option<i64> {
507 match self.stat() {
508 None => None,
509 Some(ref st) => Some(st.st_size as i64),
510 }
511 }
512
513 pub fn get_mode(&self) -> Option<uint> {
514 match self.stat() {
515 None => None,
516 Some(ref st) => Some(st.st_mode as uint),
517 }
518 }
519
520 /// Executes a function `f` on `self` as well as on all of its ancestors.
521 pub fn each_parent(&self, f: &fn(&Path)) {
522 if !self.components.is_empty() {
523 f(self);
524 self.pop().each_parent(f);
525 }
526 }
527
528 }
529
530 #[cfg(target_os = "freebsd")]
531 #[cfg(target_os = "linux")]
532 #[cfg(target_os = "macos")]
533 impl PosixPath {
534 pub fn get_atime(&self) -> Option<(i64, int)> {
535 match self.stat() {
536 None => None,
537 Some(ref st) => {
538 Some((st.st_atime as i64,
539 st.st_atime_nsec as int))
540 }
541 }
542 }
543
544 pub fn get_mtime(&self) -> Option<(i64, int)> {
545 match self.stat() {
546 None => None,
547 Some(ref st) => {
548 Some((st.st_mtime as i64,
549 st.st_mtime_nsec as int))
550 }
551 }
552 }
553
554 pub fn get_ctime(&self) -> Option<(i64, int)> {
555 match self.stat() {
556 None => None,
557 Some(ref st) => {
558 Some((st.st_ctime as i64,
559 st.st_ctime_nsec as int))
560 }
561 }
562 }
563 }
564
565 #[cfg(unix)]
566 impl PosixPath {
567 pub fn lstat(&self) -> Option<libc::stat> {
568 #[fixed_stack_segment]; #[inline(never)];
569 do self.with_c_str |buf| {
570 let mut st = stat::arch::default_stat();
571 match unsafe { libc::lstat(buf, &mut st) } {
572 0 => Some(st),
573 _ => None,
574 }
575 }
576 }
577 }
578
579 #[cfg(target_os = "freebsd")]
580 #[cfg(target_os = "macos")]
581 impl PosixPath {
582 pub fn get_birthtime(&self) -> Option<(i64, int)> {
583 match self.stat() {
584 None => None,
585 Some(ref st) => {
586 Some((st.st_birthtime as i64,
587 st.st_birthtime_nsec as int))
588 }
589 }
590 }
591 }
592
593 #[cfg(target_os = "win32")]
594 impl WindowsPath {
595 pub fn get_atime(&self) -> Option<(i64, int)> {
596 match self.stat() {
597 None => None,
598 Some(ref st) => {
599 Some((st.st_atime as i64, 0))
600 }
601 }
602 }
603
604 pub fn get_mtime(&self) -> Option<(i64, int)> {
605 match self.stat() {
606 None => None,
607 Some(ref st) => {
608 Some((st.st_mtime as i64, 0))
609 }
610 }
611 }
612
613 pub fn get_ctime(&self) -> Option<(i64, int)> {
614 match self.stat() {
615 None => None,
616 Some(ref st) => {
617 Some((st.st_ctime as i64, 0))
618 }
619 }
620 }
621
622 /// Executes a function `f` on `self` as well as on all of its ancestors.
623 pub fn each_parent(&self, f: &fn(&Path)) {
624 if !self.components.is_empty() {
625 f(self);
626 self.pop().each_parent(f);
627 }
628 }
629 }
630
631 impl ToStr for PosixPath {
632 fn to_str(&self) -> ~str {
633 let mut s = ~"";
634 if self.is_absolute {
635 s.push_str("/");
636 }
637 s + self.components.connect("/")
638 }
639 }
640
641 impl ToCStr for PosixPath {
642 fn to_c_str(&self) -> c_str::CString {
643 self.to_str().to_c_str()
644 }
645
646 unsafe fn to_c_str_unchecked(&self) -> c_str::CString {
647 self.to_str().to_c_str_unchecked()
648 }
649 }
650
651 impl GenericPath for PosixPath {
652 fn from_str(s: &str) -> PosixPath {
653 let components = s.split_iter('/')
654 .filter_map(|s| if s.is_empty() {None} else {Some(s.to_owned())})
655 .collect();
656 let is_absolute = (s.len() != 0 && s[0] == '/' as u8);
657 PosixPath {
658 is_absolute: is_absolute,
659 components: components,
660 }
661 }
662
663 fn with_dirname(&self, d: &str) -> PosixPath {
664 let dpath = PosixPath(d);
665 match self.filename() {
666 Some(ref f) => dpath.push(*f),
667 None => dpath,
668 }
669 }
670
671 fn with_filename(&self, f: &str) -> PosixPath {
672 assert!(!f.iter().all(posix::is_sep));
673 self.dir_path().push(f)
674 }
675
676 fn file_path(&self) -> PosixPath {
677 let cs = match self.filename() {
678 None => ~[],
679 Some(ref f) => ~[(*f).to_owned()]
680 };
681 PosixPath {
682 is_absolute: false,
683 components: cs,
684 }
685 }
686
687 fn push(&self, s: &str) -> PosixPath {
688 let mut v = self.components.clone();
689 for s in s.split_iter(posix::is_sep) {
690 if !s.is_empty() {
691 v.push(s.to_owned())
692 }
693 }
694 PosixPath {
695 components: v,
696 ..(*self).clone()
697 }
698 }
699
700 fn push_many<S: Str>(&self, cs: &[S]) -> PosixPath {
701 let mut v = self.components.clone();
702 for e in cs.iter() {
703 for s in e.as_slice().split_iter(posix::is_sep) {
704 if !s.is_empty() {
705 v.push(s.to_owned())
706 }
707 }
708 }
709 PosixPath {
710 is_absolute: self.is_absolute,
711 components: v,
712 }
713 }
714
715 fn pop(&self) -> PosixPath {
716 let mut cs = self.components.clone();
717 if cs.len() != 0 {
718 cs.pop();
719 }
720 PosixPath {
721 is_absolute: self.is_absolute,
722 components: cs,
723 } //..self }
724 }
725
726 fn unsafe_join(&self, other: &PosixPath) -> PosixPath {
727 if other.is_absolute {
728 PosixPath {
729 is_absolute: true,
730 components: other.components.clone(),
731 }
732 } else {
733 self.push_rel(other)
734 }
735 }
736
737 fn is_restricted(&self) -> bool {
738 false
739 }
740
741 fn normalize(&self) -> PosixPath {
742 PosixPath {
743 is_absolute: self.is_absolute,
744 components: normalize(self.components),
745 } // ..self }
746 }
747
748 fn is_absolute(&self) -> bool {
749 self.is_absolute
750 }
751
752 fn components<'a>(&'a self) -> &'a [~str] { self.components.as_slice() }
753
754 }
755
756
757 impl ToStr for WindowsPath {
758 fn to_str(&self) -> ~str {
759 let mut s = ~"";
760 match self.host {
761 Some(ref h) => {
762 s.push_str("\\\\");
763 s.push_str(*h);
764 }
765 None => { }
766 }
767 match self.device {
768 Some(ref d) => {
769 s.push_str(*d);
770 s.push_str(":");
771 }
772 None => { }
773 }
774 if self.is_absolute {
775 s.push_str("\\");
776 }
777 s + self.components.connect("\\")
778 }
779 }
780
781 impl c_str::ToCStr for WindowsPath {
782 fn to_c_str(&self) -> c_str::CString {
783 self.to_str().to_c_str()
784 }
785
786 unsafe fn to_c_str_unchecked(&self) -> c_str::CString {
787 self.to_str().to_c_str_unchecked()
788 }
789 }
790
791 impl GenericPath for WindowsPath {
792 fn from_str(s: &str) -> WindowsPath {
793 let host;
794 let device;
795 let rest;
796
797 match (
798 windows::extract_drive_prefix(s),
799 windows::extract_unc_prefix(s),
800 ) {
801 (Some((ref d, ref r)), _) => {
802 host = None;
803 device = Some((*d).clone());
804 rest = (*r).clone();
805 }
806 (None, Some((ref h, ref r))) => {
807 host = Some((*h).clone());
808 device = None;
809 rest = (*r).clone();
810 }
811 (None, None) => {
812 host = None;
813 device = None;
814 rest = s.to_owned();
815 }
816 }
817
818 let components = rest.split_iter(windows::is_sep)
819 .filter_map(|s| if s.is_empty() {None} else {Some(s.to_owned())})
820 .collect();
821
822 let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0] as char));
823 WindowsPath {
824 host: host,
825 device: device,
826 is_absolute: is_absolute,
827 components: components,
828 }
829 }
830
831 fn with_dirname(&self, d: &str) -> WindowsPath {
832 let dpath = WindowsPath(d);
833 match self.filename() {
834 Some(ref f) => dpath.push(*f),
835 None => dpath,
836 }
837 }
838
839 fn with_filename(&self, f: &str) -> WindowsPath {
840 assert!(! f.iter().all(windows::is_sep));
841 self.dir_path().push(f)
842 }
843
844 fn file_path(&self) -> WindowsPath {
845 WindowsPath {
846 host: None,
847 device: None,
848 is_absolute: false,
849 components: match self.filename() {
850 None => ~[],
851 Some(ref f) => ~[(*f).to_owned()],
852 }
853 }
854 }
855
856 fn push(&self, s: &str) -> WindowsPath {
857 let mut v = self.components.clone();
858 for s in s.split_iter(windows::is_sep) {
859 if !s.is_empty() {
860 v.push(s.to_owned())
861 }
862 }
863 WindowsPath { components: v, ..(*self).clone() }
864 }
865
866 fn push_many<S: Str>(&self, cs: &[S]) -> WindowsPath {
867 let mut v = self.components.clone();
868 for e in cs.iter() {
869 for s in e.as_slice().split_iter(windows::is_sep) {
870 if !s.is_empty() {
871 v.push(s.to_owned())
872 }
873 }
874 }
875 // tedious, but as-is, we can't use ..self
876 WindowsPath {
877 host: self.host.clone(),
878 device: self.device.clone(),
879 is_absolute: self.is_absolute,
880 components: v
881 }
882 }
883
884 fn pop(&self) -> WindowsPath {
885 let mut cs = self.components.clone();
886 if cs.len() != 0 {
887 cs.pop();
888 }
889 WindowsPath {
890 host: self.host.clone(),
891 device: self.device.clone(),
892 is_absolute: self.is_absolute,
893 components: cs,
894 }
895 }
896
897 fn unsafe_join(&self, other: &WindowsPath) -> WindowsPath {
898 /* rhs not absolute is simple push */
899 if !other.is_absolute {
900 return self.push_many(other.components);
901 }
902
903 /* if rhs has a host set, then the whole thing wins */
904 match other.host {
905 Some(ref host) => {
906 return WindowsPath {
907 host: Some((*host).clone()),
908 device: other.device.clone(),
909 is_absolute: true,
910 components: other.components.clone(),
911 };
912 }
913 _ => {}
914 }
915
916 /* if rhs has a device set, then a part wins */
917 match other.device {
918 Some(ref device) => {
919 return WindowsPath {
920 host: None,
921 device: Some((*device).clone()),
922 is_absolute: true,
923 components: other.components.clone(),
924 };
925 }
926 _ => {}
927 }
928
929 /* fallback: host and device of lhs win, but the
930 whole path of the right */
931 WindowsPath {
932 host: self.host.clone(),
933 device: self.device.clone(),
934 is_absolute: self.is_absolute || other.is_absolute,
935 components: other.components.clone(),
936 }
937 }
938
939 fn is_restricted(&self) -> bool {
940 match self.filestem() {
941 Some(stem) => {
942 // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
943 // to_ascii_move and to_str_move to not do a unnecessary copy.
944 match stem.to_ascii().to_lower().to_str_ascii() {
945 ~"con" | ~"aux" | ~"com1" | ~"com2" | ~"com3" | ~"com4" |
946 ~"lpt1" | ~"lpt2" | ~"lpt3" | ~"prn" | ~"nul" => true,
947 _ => false
948 }
949 },
950 None => false
951 }
952 }
953
954 fn normalize(&self) -> WindowsPath {
955 WindowsPath {
956 host: self.host.clone(),
957 device: match self.device {
958 None => None,
959
960 // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
961 // to_ascii_move and to_str_move to not do a unnecessary copy.
962 Some(ref device) => Some(device.to_ascii().to_upper().to_str_ascii())
963 },
964 is_absolute: self.is_absolute,
965 components: normalize(self.components)
966 }
967 }
968
969 fn is_absolute(&self) -> bool {
970 self.is_absolute
971 }
972
973 fn components<'a>(&'a self) -> &'a [~str] { self.components.as_slice() }
974
975 }
976
977 pub fn normalize(components: &[~str]) -> ~[~str] {
978 let mut cs = ~[];
979 for c in components.iter() {
980 if *c == ~"." && components.len() > 1 { loop; }
981 if *c == ~"" { loop; }
982 if *c == ~".." && cs.len() != 0 {
983 cs.pop();
984 loop;
985 }
986 cs.push((*c).clone());
987 }
988 cs
989 }
990
991 // Various posix helpers.
992 pub mod posix {
993
994 #[inline]
995 pub fn is_sep(u: char) -> bool {
996 u == '/'
997 }
998
999 }
1000
1001 // Various windows helpers.
1002 pub mod windows {
1003 use libc;
1004 use option::{None, Option, Some};
1005
1006 #[inline]
1007 pub fn is_sep(u: char) -> bool {
1008 u == '/' || u == '\\'
1009 }
1010
1011 pub fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> {
1012 if (s.len() > 1 &&
1013 (s[0] == '\\' as u8 || s[0] == '/' as u8) &&
1014 s[0] == s[1]) {
1015 let mut i = 2;
1016 while i < s.len() {
1017 if is_sep(s[i] as char) {
1018 let pre = s.slice(2, i).to_owned();
1019 let rest = s.slice(i, s.len()).to_owned();
1020 return Some((pre, rest));
1021 }
1022 i += 1;
1023 }
1024 }
1025 None
1026 }
1027
1028 pub fn extract_drive_prefix(s: &str) -> Option<(~str,~str)> {
1029 #[fixed_stack_segment]; #[inline(never)];
1030
1031 unsafe {
1032 if (s.len() > 1 &&
1033 libc::isalpha(s[0] as libc::c_int) != 0 &&
1034 s[1] == ':' as u8) {
1035 let rest = if s.len() == 2 {
1036 ~""
1037 } else {
1038 s.slice(2, s.len()).to_owned()
1039 };
1040 return Some((s.slice(0,1).to_owned(), rest));
1041 }
1042 None
1043 }
1044 }
1045 }
1046
1047 #[cfg(test)]
1048 mod tests {
1049 use option::{None, Some};
1050 use path::{PosixPath, WindowsPath, windows};
1051
1052 #[test]
1053 fn test_double_slash_collapsing() {
1054 let path = PosixPath("tmp/");
1055 let path = path.push("/hmm");
1056 let path = path.normalize();
1057 assert_eq!(~"tmp/hmm", path.to_str());
1058
1059 let path = WindowsPath("tmp/");
1060 let path = path.push("/hmm");
1061 let path = path.normalize();
1062 assert_eq!(~"tmp\\hmm", path.to_str());
1063 }
1064
1065 #[test]
1066 fn test_filetype_foo_bar() {
1067 let wp = PosixPath("foo.bar");
1068 assert_eq!(wp.filetype(), Some(".bar"));
1069
1070 let wp = WindowsPath("foo.bar");
1071 assert_eq!(wp.filetype(), Some(".bar"));
1072 }
1073
1074 #[test]
1075 fn test_filetype_foo() {
1076 let wp = PosixPath("foo");
1077 assert_eq!(wp.filetype(), None);
1078
1079 let wp = WindowsPath("foo");
1080 assert_eq!(wp.filetype(), None);
1081 }
1082
1083 #[test]
1084 fn test_posix_paths() {
1085 fn t(wp: &PosixPath, s: &str) {
1086 let ss = wp.to_str();
1087 let sss = s.to_owned();
1088 if (ss != sss) {
1089 debug!("got %s", ss);
1090 debug!("expected %s", sss);
1091 assert_eq!(ss, sss);
1092 }
1093 }
1094
1095 t(&(PosixPath("hi")), "hi");
1096 t(&(PosixPath("/lib")), "/lib");
1097 t(&(PosixPath("hi/there")), "hi/there");
1098 t(&(PosixPath("hi/there.txt")), "hi/there.txt");
1099
1100 t(&(PosixPath("hi/there.txt")), "hi/there.txt");
1101 t(&(PosixPath("hi/there.txt")
1102 .with_filetype("")), "hi/there");
1103
1104 t(&(PosixPath("/a/b/c/there.txt")
1105 .with_dirname("hi")), "hi/there.txt");
1106
1107 t(&(PosixPath("hi/there.txt")
1108 .with_dirname(".")), "./there.txt");
1109
1110 t(&(PosixPath("a/b/c")
1111 .push("..")), "a/b/c/..");
1112
1113 t(&(PosixPath("there.txt")
1114 .with_filetype("o")), "there.o");
1115
1116 t(&(PosixPath("hi/there.txt")
1117 .with_filetype("o")), "hi/there.o");
1118
1119 t(&(PosixPath("hi/there.txt")
1120 .with_filetype("o")
1121 .with_dirname("/usr/lib")),
1122 "/usr/lib/there.o");
1123
1124 t(&(PosixPath("hi/there.txt")
1125 .with_filetype("o")
1126 .with_dirname("/usr/lib/")),
1127 "/usr/lib/there.o");
1128
1129 t(&(PosixPath("hi/there.txt")
1130 .with_filetype("o")
1131 .with_dirname("/usr//lib//")),
1132 "/usr/lib/there.o");
1133
1134 t(&(PosixPath("/usr/bin/rust")
1135 .push_many([~"lib", ~"thingy.so"])
1136 .with_filestem("librustc")),
1137 "/usr/bin/rust/lib/librustc.so");
1138
1139 }
1140
1141 #[test]
1142 fn test_posix_push_with_backslash() {
1143 let a = PosixPath("/aaa/bbb");
1144 let b = a.push("x\\y"); // \ is not a file separator for posix paths
1145 assert_eq!(a.components.len(), 2);
1146 assert_eq!(b.components.len(), 3);
1147 }
1148
1149 #[test]
1150 fn test_normalize() {
1151 fn t(wp: &PosixPath, s: &str) {
1152 let ss = wp.to_str();
1153 let sss = s.to_owned();
1154 if (ss != sss) {
1155 debug!("got %s", ss);
1156 debug!("expected %s", sss);
1157 assert_eq!(ss, sss);
1158 }
1159 }
1160
1161 t(&(PosixPath("hi/there.txt")
1162 .with_dirname(".").normalize()), "there.txt");
1163
1164 t(&(PosixPath("a/b/../c/././/../foo.txt/").normalize()),
1165 "a/foo.txt");
1166
1167 t(&(PosixPath("a/b/c")
1168 .push("..").normalize()), "a/b");
1169 }
1170
1171 #[test]
1172 fn test_extract_unc_prefixes() {
1173 assert!(windows::extract_unc_prefix("\\\\").is_none());
1174 assert!(windows::extract_unc_prefix("//").is_none());
1175 assert!(windows::extract_unc_prefix("\\\\hi").is_none());
1176 assert!(windows::extract_unc_prefix("//hi").is_none());
1177 assert!(windows::extract_unc_prefix("\\\\hi\\") ==
1178 Some((~"hi", ~"\\")));
1179 assert!(windows::extract_unc_prefix("//hi\\") ==
1180 Some((~"hi", ~"\\")));
1181 assert!(windows::extract_unc_prefix("\\\\hi\\there") ==
1182 Some((~"hi", ~"\\there")));
1183 assert!(windows::extract_unc_prefix("//hi/there") ==
1184 Some((~"hi", ~"/there")));
1185 assert!(windows::extract_unc_prefix(
1186 "\\\\hi\\there\\friends.txt") ==
1187 Some((~"hi", ~"\\there\\friends.txt")));
1188 assert!(windows::extract_unc_prefix(
1189 "//hi\\there\\friends.txt") ==
1190 Some((~"hi", ~"\\there\\friends.txt")));
1191 }
1192
1193 #[test]
1194 fn test_extract_drive_prefixes() {
1195 assert!(windows::extract_drive_prefix("c").is_none());
1196 assert!(windows::extract_drive_prefix("c:") ==
1197 Some((~"c", ~"")));
1198 assert!(windows::extract_drive_prefix("d:") ==
1199 Some((~"d", ~"")));
1200 assert!(windows::extract_drive_prefix("z:") ==
1201 Some((~"z", ~"")));
1202 assert!(windows::extract_drive_prefix("c:\\hi") ==
1203 Some((~"c", ~"\\hi")));
1204 assert!(windows::extract_drive_prefix("d:hi") ==
1205 Some((~"d", ~"hi")));
1206 assert!(windows::extract_drive_prefix("c:hi\\there.txt") ==
1207 Some((~"c", ~"hi\\there.txt")));
1208 assert!(windows::extract_drive_prefix("c:\\hi\\there.txt") ==
1209 Some((~"c", ~"\\hi\\there.txt")));
1210 }
1211
1212 #[test]
1213 fn test_windows_paths() {
1214 fn t(wp: &WindowsPath, s: &str) {
1215 let ss = wp.to_str();
1216 let sss = s.to_owned();
1217 if (ss != sss) {
1218 debug!("got %s", ss);
1219 debug!("expected %s", sss);
1220 assert_eq!(ss, sss);
1221 }
1222 }
1223
1224 t(&(WindowsPath("hi")), "hi");
1225 t(&(WindowsPath("hi/there")), "hi\\there");
1226 t(&(WindowsPath("hi/there.txt")), "hi\\there.txt");
1227
1228 t(&(WindowsPath("there.txt")
1229 .with_filetype("o")), "there.o");
1230
1231 t(&(WindowsPath("hi/there.txt")
1232 .with_filetype("o")), "hi\\there.o");
1233
1234 t(&(WindowsPath("hi/there.txt")
1235 .with_filetype("o")
1236 .with_dirname("c:\\program files A")),
1237 "c:\\program files A\\there.o");
1238
1239 t(&(WindowsPath("hi/there.txt")
1240 .with_filetype("o")
1241 .with_dirname("c:\\program files B\\")),
1242 "c:\\program files B\\there.o");
1243
1244 t(&(WindowsPath("hi/there.txt")
1245 .with_filetype("o")
1246 .with_dirname("c:\\program files C\\/")),
1247 "c:\\program files C\\there.o");
1248
1249 t(&(WindowsPath("c:\\program files (x86)\\rust")
1250 .push_many([~"lib", ~"thingy.dll"])
1251 .with_filename("librustc.dll")),
1252 "c:\\program files (x86)\\rust\\lib\\librustc.dll");
1253
1254 t(&(WindowsPath("\\\\computer\\share")
1255 .unsafe_join(&WindowsPath("\\a"))),
1256 "\\\\computer\\a");
1257
1258 t(&(WindowsPath("//computer/share")
1259 .unsafe_join(&WindowsPath("\\a"))),
1260 "\\\\computer\\a");
1261
1262 t(&(WindowsPath("//computer/share")
1263 .unsafe_join(&WindowsPath("\\\\computer\\share"))),
1264 "\\\\computer\\share");
1265
1266 t(&(WindowsPath("C:/whatever")
1267 .unsafe_join(&WindowsPath("//computer/share/a/b"))),
1268 "\\\\computer\\share\\a\\b");
1269
1270 t(&(WindowsPath("C:")
1271 .unsafe_join(&WindowsPath("D:/foo"))),
1272 "D:\\foo");
1273
1274 t(&(WindowsPath("C:")
1275 .unsafe_join(&WindowsPath("B"))),
1276 "C:B");
1277
1278 t(&(WindowsPath("C:")
1279 .unsafe_join(&WindowsPath("/foo"))),
1280 "C:\\foo");
1281
1282 t(&(WindowsPath("C:\\")
1283 .unsafe_join(&WindowsPath("\\bar"))),
1284 "C:\\bar");
1285
1286 t(&(WindowsPath("")
1287 .unsafe_join(&WindowsPath(""))),
1288 "");
1289
1290 t(&(WindowsPath("")
1291 .unsafe_join(&WindowsPath("a"))),
1292 "a");
1293
1294 t(&(WindowsPath("")
1295 .unsafe_join(&WindowsPath("C:\\a"))),
1296 "C:\\a");
1297
1298 t(&(WindowsPath("c:\\foo")
1299 .normalize()),
1300 "C:\\foo");
1301 }
1302
1303 #[test]
1304 fn test_windows_path_restrictions() {
1305 assert_eq!(WindowsPath("hi").is_restricted(), false);
1306 assert_eq!(WindowsPath("C:\\NUL").is_restricted(), true);
1307 assert_eq!(WindowsPath("C:\\COM1.TXT").is_restricted(), true);
1308 assert_eq!(WindowsPath("c:\\prn.exe").is_restricted(), true);
1309 }
1310
1311 #[test]
1312 fn test_is_ancestor_of() {
1313 assert!(&PosixPath("/a/b").is_ancestor_of(&PosixPath("/a/b/c/d")));
1314 assert!(!&PosixPath("/a/b/c/d").is_ancestor_of(&PosixPath("/a/b")));
1315 assert!(!&PosixPath("/a/b").is_ancestor_of(&PosixPath("/c/d")));
1316 assert!(&PosixPath("/a/b").is_ancestor_of(&PosixPath("/a/b/c/d")));
1317 assert!(&PosixPath("/").is_ancestor_of(&PosixPath("/a/b/c")));
1318 assert!(!&PosixPath("/").is_ancestor_of(&PosixPath("")));
1319 assert!(!&PosixPath("/a/b/c").is_ancestor_of(&PosixPath("")));
1320 assert!(!&PosixPath("").is_ancestor_of(&PosixPath("/a/b/c")));
1321
1322 assert!(&WindowsPath("C:\\a\\b").is_ancestor_of(&WindowsPath("C:\\a\\b\\c\\d")));
1323 assert!(!&WindowsPath("C:\\a\\b\\c\\d").is_ancestor_of(&WindowsPath("C:\\a\\b")));
1324 assert!(!&WindowsPath("C:\\a\\b").is_ancestor_of(&WindowsPath("C:\\c\\d")));
1325 assert!(&WindowsPath("C:\\a\\b").is_ancestor_of(&WindowsPath("C:\\a\\b\\c\\d")));
1326 assert!(&WindowsPath("C:\\").is_ancestor_of(&WindowsPath("C:\\a\\b\\c")));
1327 assert!(!&WindowsPath("C:\\").is_ancestor_of(&WindowsPath("")));
1328 assert!(!&WindowsPath("C:\\a\\b\\c").is_ancestor_of(&WindowsPath("")));
1329 assert!(!&WindowsPath("").is_ancestor_of(&WindowsPath("C:\\a\\b\\c")));
1330
1331 }
1332
1333 #[test]
1334 fn test_relative_to1() {
1335 let p1 = PosixPath("/usr/bin/rustc");
1336 let p2 = PosixPath("/usr/lib/mylib");
1337 let res = p1.get_relative_to(&p2);
1338 assert_eq!(res, PosixPath("../lib"));
1339
1340 let p1 = WindowsPath("C:\\usr\\bin\\rustc");
1341 let p2 = WindowsPath("C:\\usr\\lib\\mylib");
1342 let res = p1.get_relative_to(&p2);
1343 assert_eq!(res, WindowsPath("..\\lib"));
1344
1345 }
1346
1347 #[test]
1348 fn test_relative_to2() {
1349 let p1 = PosixPath("/usr/bin/rustc");
1350 let p2 = PosixPath("/usr/bin/../lib/mylib");
1351 let res = p1.get_relative_to(&p2);
1352 assert_eq!(res, PosixPath("../lib"));
1353
1354 let p1 = WindowsPath("C:\\usr\\bin\\rustc");
1355 let p2 = WindowsPath("C:\\usr\\bin\\..\\lib\\mylib");
1356 let res = p1.get_relative_to(&p2);
1357 assert_eq!(res, WindowsPath("..\\lib"));
1358 }
1359
1360 #[test]
1361 fn test_relative_to3() {
1362 let p1 = PosixPath("/usr/bin/whatever/rustc");
1363 let p2 = PosixPath("/usr/lib/whatever/mylib");
1364 let res = p1.get_relative_to(&p2);
1365 assert_eq!(res, PosixPath("../../lib/whatever"));
1366
1367 let p1 = WindowsPath("C:\\usr\\bin\\whatever\\rustc");
1368 let p2 = WindowsPath("C:\\usr\\lib\\whatever\\mylib");
1369 let res = p1.get_relative_to(&p2);
1370 assert_eq!(res, WindowsPath("..\\..\\lib\\whatever"));
1371
1372 }
1373
1374 #[test]
1375 fn test_relative_to4() {
1376 let p1 = PosixPath("/usr/bin/whatever/../rustc");
1377 let p2 = PosixPath("/usr/lib/whatever/mylib");
1378 let res = p1.get_relative_to(&p2);
1379 assert_eq!(res, PosixPath("../lib/whatever"));
1380
1381 let p1 = WindowsPath("C:\\usr\\bin\\whatever\\..\\rustc");
1382 let p2 = WindowsPath("C:\\usr\\lib\\whatever\\mylib");
1383 let res = p1.get_relative_to(&p2);
1384 assert_eq!(res, WindowsPath("..\\lib\\whatever"));
1385
1386 }
1387
1388 #[test]
1389 fn test_relative_to5() {
1390 let p1 = PosixPath("/usr/bin/whatever/../rustc");
1391 let p2 = PosixPath("/usr/lib/whatever/../mylib");
1392 let res = p1.get_relative_to(&p2);
1393 assert_eq!(res, PosixPath("../lib"));
1394
1395 let p1 = WindowsPath("C:\\usr\\bin/whatever\\..\\rustc");
1396 let p2 = WindowsPath("C:\\usr\\lib\\whatever\\..\\mylib");
1397 let res = p1.get_relative_to(&p2);
1398 assert_eq!(res, WindowsPath("..\\lib"));
1399 }
1400
1401 #[test]
1402 fn test_relative_to6() {
1403 let p1 = PosixPath("/1");
1404 let p2 = PosixPath("/2/3");
1405 let res = p1.get_relative_to(&p2);
1406 assert_eq!(res, PosixPath("2"));
1407
1408 let p1 = WindowsPath("C:\\1");
1409 let p2 = WindowsPath("C:\\2\\3");
1410 let res = p1.get_relative_to(&p2);
1411 assert_eq!(res, WindowsPath("2"));
1412
1413 }
1414
1415 #[test]
1416 fn test_relative_to7() {
1417 let p1 = PosixPath("/1/2");
1418 let p2 = PosixPath("/3");
1419 let res = p1.get_relative_to(&p2);
1420 assert_eq!(res, PosixPath(".."));
1421
1422 let p1 = WindowsPath("C:\\1\\2");
1423 let p2 = WindowsPath("C:\\3");
1424 let res = p1.get_relative_to(&p2);
1425 assert_eq!(res, WindowsPath(".."));
1426
1427 }
1428
1429 #[test]
1430 fn test_relative_to8() {
1431 let p1 = PosixPath("/home/brian/Dev/rust/build/").push_rel(
1432 &PosixPath("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
1433 let p2 = PosixPath("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
1434 &PosixPath("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
1435 let res = p1.get_relative_to(&p2);
1436 debug!("test_relative_to8: %s vs. %s",
1437 res.to_str(),
1438 PosixPath(".").to_str());
1439 assert_eq!(res, PosixPath("."));
1440
1441 let p1 = WindowsPath("C:\\home\\brian\\Dev\\rust\\build\\").push_rel(
1442 &WindowsPath("stage2\\lib\\rustc\\i686-unknown-linux-gnu\\lib\\librustc.so"));
1443 let p2 = WindowsPath("\\home\\brian\\Dev\\rust\\build\\stage2\\bin\\..").push_rel(
1444 &WindowsPath("lib\\rustc\\i686-unknown-linux-gnu\\lib\\libstd.so"));
1445 let res = p1.get_relative_to(&p2);
1446 debug!("test_relative_to8: %s vs. %s",
1447 res.to_str(),
1448 WindowsPath(".").to_str());
1449 assert_eq!(res, WindowsPath("."));
1450
1451 }
1452
1453 }
libstd/path.rs:45:1-45:1 -fn- definition:
pub fn WindowsPath(s: &str) -> WindowsPath {
references:-832: let dpath = WindowsPath(d);
libstd/path.rs:38:23-38:23 -struct- definition:
#[deriving(Clone, Eq)]
pub struct WindowsPath {
references:-897: fn unsafe_join(&self, other: &WindowsPath) -> WindowsPath {
955: WindowsPath {
38: #[deriving(Clone, Eq)]
38: #[deriving(Clone, Eq)]
839: fn with_filename(&self, f: &str) -> WindowsPath {
931: WindowsPath {
38: #[deriving(Clone, Eq)]
897: fn unsafe_join(&self, other: &WindowsPath) -> WindowsPath {
823: WindowsPath {
792: fn from_str(s: &str) -> WindowsPath {
906: return WindowsPath {
863: WindowsPath { components: v, ..(*self).clone() }
38: #[deriving(Clone, Eq)]
781: impl c_str::ToCStr for WindowsPath {
38: #[deriving(Clone, Eq)]
38: #[deriving(Clone, Eq)]
954: fn normalize(&self) -> WindowsPath {
919: return WindowsPath {
791: impl GenericPath for WindowsPath {
856: fn push(&self, s: &str) -> WindowsPath {
38: #[deriving(Clone, Eq)]
876: WindowsPath {
889: WindowsPath {
38: #[deriving(Clone, Eq)]
845: WindowsPath {
844: fn file_path(&self) -> WindowsPath {
757: impl ToStr for WindowsPath {
38: #[deriving(Clone, Eq)]
38: #[deriving(Clone, Eq)]
884: fn pop(&self) -> WindowsPath {
(866)(831)(46)(38)libstd/path.rs:55:1-55:1 -fn- definition:
pub fn PosixPath(s: &str) -> PosixPath {
references:-664: let dpath = PosixPath(d);
libstd/rt/uv/uvio.rs:
2180: let mut fd = (*io).fs_open(&Path(path), create_fm, create_fa).unwrap();
2193: (*io).fs_unlink(&Path(path));
634: path: Path(path_str),
723: paths.push(Path(path_str+"/"+*r));
2187: let mut fd = (*io).fs_open(&Path(path), ro_fm, ro_fa).unwrap();
libstd/os.rs:
591: Path("/data/tmp")
537: Some(Path(*p))
593: getenv_nonempty("TMPDIR").unwrap_or(Path("/tmp"))
517: load_self().map_move(|path| Path(path).dir_path())
81: Path(str::raw::from_c_str(buf as *c_char))
582: Some(Path(x))
libstd/path.rs:1028:4-1028:4 -fn- definition:
pub fn extract_drive_prefix(s: &str) -> Option<(~str,~str)> {
#[fixed_stack_segment]; #[inline(never)];
references:-798: windows::extract_drive_prefix(s),
libstd/path.rs:976:1-976:1 -fn- definition:
pub fn normalize(components: &[~str]) -> ~[~str] {
references:-744: components: normalize(self.components),
965: components: normalize(self.components)
libstd/path.rs:995:4-995:4 -fn- definition:
pub fn is_sep(u: char) -> bool {
u == '/'
references:-672: assert!(!f.iter().all(posix::is_sep));
689: for s in s.split_iter(posix::is_sep) {
703: for s in e.as_slice().split_iter(posix::is_sep) {
libstd/path.rs:1007:4-1007:4 -fn- definition:
pub fn is_sep(u: char) -> bool {
u == '/' || u == '\\'
references:-869: for s in e.as_slice().split_iter(windows::is_sep) {
858: for s in s.split_iter(windows::is_sep) {
1017: if is_sep(s[i] as char) {
840: assert!(! f.iter().all(windows::is_sep));
822: let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0] as char));
818: let components = rest.split_iter(windows::is_sep)
libstd/path.rs:50:23-50:23 -struct- definition:
#[deriving(Clone, Eq)]
pub struct PosixPath {
references:-50: #[deriving(Clone, Eq)]
687: fn push(&self, s: &str) -> PosixPath {
50: #[deriving(Clone, Eq)]
50: #[deriving(Clone, Eq)]
657: PosixPath {
652: fn from_str(s: &str) -> PosixPath {
487: impl PosixPath {
694: PosixPath {
742: PosixPath {
50: #[deriving(Clone, Eq)]
681: PosixPath {
50: #[deriving(Clone, Eq)]
50: #[deriving(Clone, Eq)]
726: fn unsafe_join(&self, other: &PosixPath) -> PosixPath {
715: fn pop(&self) -> PosixPath {
676: fn file_path(&self) -> PosixPath {
631: impl ToStr for PosixPath {
50: #[deriving(Clone, Eq)]
651: impl GenericPath for PosixPath {
641: impl ToCStr for PosixPath {
50: #[deriving(Clone, Eq)]
726: fn unsafe_join(&self, other: &PosixPath) -> PosixPath {
50: #[deriving(Clone, Eq)]
533: impl PosixPath {
566: impl PosixPath {
663: fn with_dirname(&self, d: &str) -> PosixPath {
671: fn with_filename(&self, f: &str) -> PosixPath {
700: fn push_many<S: Str>(&self, cs: &[S]) -> PosixPath {
728: PosixPath {
720: PosixPath {
(741)(50)(50)(521)(709)(56)libstd/run.rs:
(80)(795)(638)libstd/unstable/dynamic_lib.rs:
(150)(44)libstd/rt/io/mod.rs:
(626)libstd/rt/io/file.rs:
(679)(564)(449)(282)(685)(569)(565)libstd/rt/io/support.rs:
(23)libstd/rt/rtio.rs:
(65)(86)libstd/rt/uv/uvio.rs:
(706)(703)libstd/io.rs:
(1064)(1793)(1626)(1323)(1620)(1781)libstd/os.rs:
(626)(534)(980)(607)(706)(906)(862)(991)(573)(991)(655)(965)(616)(807)(576)(72)(877)(888)(835)(589)(813)(717)(645)(888)(807)(906)(645)(689)(850)(607)..3more..
libstd/path.rs:335:8-335:8 -fn- definition:
pub fn default_stat() -> libc::stat {
libc::stat {
references:-570: let mut st = stat::arch::default_stat();
491: let mut st = stat::arch::default_stat();
libstd/path.rs:1011:4-1011:4 -fn- definition:
pub fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> {
if (s.len() > 1 &&
references:-799: windows::extract_unc_prefix(s),
libstd/path.rs:59:1-59:1 -trait- definition:
pub trait GenericPath : Clone + Eq + ToStr {
references:-175: fn unsafe_join(&self, (&Self)) -> Self;
202: fn get_relative_to(&self, abs2: (&Self)) -> Self {
157: fn push(&self, (&str)) -> Self;
124: fn with_filestem(&self, s: &str) -> Self {
160: fn push_rel(&self, other: &Self) -> Self {
160: fn push_rel(&self, other: &Self) -> Self {
227: let mut result: Self = GenericPath::from_str(".");
192: fn is_ancestor_of(&self, other: &Self) -> bool {
651: impl GenericPath for PosixPath {
791: impl GenericPath for WindowsPath {
144: fn dir_path(&self) -> Self {
175: fn unsafe_join(&self, (&Self)) -> Self;
133: fn with_filetype(&self, t: &str) -> Self {
171: fn pop(&self) -> Self;
62: fn from_str(&str) -> Self;
230: let p: Self = GenericPath::from_str("");
202: fn get_relative_to(&self, abs2: (&Self)) -> Self {
153: fn file_path(&self) -> Self;
120: fn with_filename(&self, (&str)) -> Self;
167: fn push_many<S: Str>(&self, (&[S])) -> Self;
185: fn normalize(&self) -> Self;
116: fn with_dirname(&self, (&str)) -> Self;