comparison src/dired.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents 6719134a07c2
children 2f8bb876ab1d
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
29 #include "regex.h" 29 #include "regex.h"
30 #include "opaque.h" 30 #include "opaque.h"
31 #include "sysfile.h" 31 #include "sysfile.h"
32 #include "sysdir.h" 32 #include "sysdir.h"
33 #include "systime.h" 33 #include "systime.h"
34 #include "sysdep.h"
34 #include "syspwd.h" 35 #include "syspwd.h"
35 36
36 Lisp_Object Vcompletion_ignored_extensions; 37 Lisp_Object Vcompletion_ignored_extensions;
37 Lisp_Object Qdirectory_files; 38 Lisp_Object Qdirectory_files;
38 Lisp_Object Qfile_name_completion; 39 Lisp_Object Qfile_name_completion;
137 && (NILP (match) 138 && (NILP (match)
138 || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)))) 139 || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0))))
139 { 140 {
140 if (!NILP (files_only)) 141 if (!NILP (files_only))
141 { 142 {
142 int dir_p;
143 struct stat st; 143 struct stat st;
144 char *cur_statbuf = statbuf; 144 int dir_p = 0;
145 char *cur_statbuf_tail = statbuf_tail; 145
146 146 memcpy (statbuf_tail, dp->d_name, len);
147 /* #### I don't think the code under `if' is necessary 147 statbuf_tail[len] = 0;
148 anymore. The crashes in this function were reported 148
149 because MAXNAMLEN was used to remember the *whole* 149 if (stat (statbuf, &st) == 0
150 statbuf, instead of using MAXPATHLEN. This should be 150 && (st.st_mode & S_IFMT) == S_IFDIR)
151 tested after 21.0 is released. */ 151 dir_p = 1;
152
153 /* We normally use the buffer created by alloca.
154 However, if the file name we get too big, we'll use a
155 malloced buffer, and free it. It is undefined how
156 stat() will react to this, but we avoid a buffer
157 overrun. */
158 if (len > MAXNAMLEN)
159 {
160 cur_statbuf = (char *)xmalloc (directorylen + len + 1);
161 memcpy (cur_statbuf, statbuf, directorylen);
162 cur_statbuf_tail = cur_statbuf + directorylen;
163 }
164 memcpy (cur_statbuf_tail, dp->d_name, len);
165 cur_statbuf_tail[len] = 0;
166
167 if (stat (cur_statbuf, &st) < 0)
168 dir_p = 0;
169 else
170 dir_p = ((st.st_mode & S_IFMT) == S_IFDIR);
171
172 if (cur_statbuf != statbuf)
173 xfree (cur_statbuf);
174 152
175 if (EQ (files_only, Qt) && dir_p) 153 if (EQ (files_only, Qt) && dir_p)
176 continue; 154 continue;
177 else if (!EQ (files_only, Qt) && !dir_p) 155 else if (!EQ (files_only, Qt) && !dir_p)
178 continue; 156 continue;
562 if and only if the completion returned in the car was unique. 540 if and only if the completion returned in the car was unique.
563 */ 541 */
564 (user)) 542 (user))
565 { 543 {
566 int uniq; 544 int uniq;
567 Lisp_Object completed; 545 Lisp_Object completed = user_name_completion (user, 0, &uniq);
568
569 completed = user_name_completion (user, 0, &uniq);
570 return Fcons (completed, uniq ? Qt : Qnil); 546 return Fcons (completed, uniq ? Qt : Qnil);
571 } 547 }
572 548
573 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /* 549 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /*
574 Return a list of all completions of user name USER. 550 Return a list of all completions of user name USER.
577 (user)) 553 (user))
578 { 554 {
579 return user_name_completion (user, 1, NULL); 555 return user_name_completion (user, 1, NULL);
580 } 556 }
581 557
558 struct user_name
559 {
560 Bufbyte *ptr;
561 size_t len;
562 };
563
564 struct user_cache
565 {
566 struct user_name *user_names;
567 int length;
568 int size;
569 EMACS_TIME last_rebuild_time;
570 };
571 static struct user_cache user_cache;
572
573 static void
574 free_user_cache (struct user_cache *cache)
575 {
576 int i;
577 for (i = 0; i < cache->length; i++)
578 xfree (cache->user_names[i].ptr);
579 xfree (cache->user_names);
580 xzero (*cache);
581 }
582
582 static Lisp_Object 583 static Lisp_Object
583 user_name_completion_unwind (Lisp_Object locative) 584 user_name_completion_unwind (Lisp_Object cache_incomplete_p)
584 { 585 {
585 Lisp_Object obj1 = XCAR (locative);
586 Lisp_Object obj2 = XCDR (locative);
587 char **cache;
588 int clen, i;
589
590
591 if (!NILP (obj1) && !NILP (obj2))
592 {
593 /* clean up if interrupted building cache */
594 cache = *(char ***)get_opaque_ptr (obj1);
595 clen = *(int *)get_opaque_ptr (obj2);
596 free_opaque_ptr (obj1);
597 free_opaque_ptr (obj2);
598 for (i = 0; i < clen; i++)
599 free (cache[i]);
600 free (cache);
601 }
602
603 free_cons (XCONS (locative));
604 endpwent (); 586 endpwent ();
587 speed_up_interrupts ();
588
589 if (! NILP (XCAR (cache_incomplete_p)))
590 free_user_cache (&user_cache);
591
592 free_cons (XCONS (cache_incomplete_p));
605 593
606 return Qnil; 594 return Qnil;
607 } 595 }
608 596
609 static char **user_cache; 597 #define USER_CACHE_TTL (24*60*60) /* Time to live: 1 day, in seconds */
610 static int user_cache_len;
611 static int user_cache_max;
612 static long user_cache_time;
613
614 #define USER_CACHE_REBUILD (24*60*60) /* 1 day, in seconds */
615 598
616 static Lisp_Object 599 static Lisp_Object
617 user_name_completion (Lisp_Object user, int all_flag, int *uniq) 600 user_name_completion (Lisp_Object user, int all_flag, int *uniq)
618 { 601 {
619 /* This function can GC */ 602 /* This function can GC */
620 struct passwd *pw;
621 int matchcount = 0; 603 int matchcount = 0;
622 Lisp_Object bestmatch = Qnil; 604 Lisp_Object bestmatch = Qnil;
623 Charcount bestmatchsize = 0; 605 Charcount bestmatchsize = 0;
624 int speccount = specpdl_depth ();
625 int i, cmax, clen;
626 char **cache;
627 Charcount user_name_length; 606 Charcount user_name_length;
628 Lisp_Object locative;
629 EMACS_TIME t; 607 EMACS_TIME t;
608 int i;
630 struct gcpro gcpro1, gcpro2; 609 struct gcpro gcpro1, gcpro2;
631 610
632 GCPRO2 (user, bestmatch); 611 GCPRO2 (user, bestmatch);
633 612
634 CHECK_STRING (user); 613 CHECK_STRING (user);
636 user_name_length = XSTRING_CHAR_LENGTH (user); 615 user_name_length = XSTRING_CHAR_LENGTH (user);
637 616
638 /* Cache user name lookups because it tends to be quite slow. 617 /* Cache user name lookups because it tends to be quite slow.
639 * Rebuild the cache occasionally to catch changes */ 618 * Rebuild the cache occasionally to catch changes */
640 EMACS_GET_TIME (t); 619 EMACS_GET_TIME (t);
641 if (user_cache && 620 if (user_cache.user_names &&
642 EMACS_SECS (t) - user_cache_time > USER_CACHE_REBUILD) 621 (EMACS_SECS (t) - EMACS_SECS (user_cache.last_rebuild_time)
643 { 622 > USER_CACHE_TTL))
644 for (i = 0; i < user_cache_len; i++) 623 free_user_cache (&user_cache);
645 free (user_cache[i]); 624
646 free (user_cache); 625 if (!user_cache.user_names)
647 user_cache = NULL; 626 {
648 user_cache_len = 0; 627 struct passwd *pwd;
649 user_cache_max = 0; 628 Lisp_Object cache_incomplete_p = noseeum_cons (Qt, Qnil);
650 } 629 int speccount = specpdl_depth ();
651 630
652 if (user_cache == NULL || user_cache_max <= 0) 631 slow_down_interrupts ();
653 {
654 cmax = 200;
655 clen = 0;
656 cache = (char **) malloc (cmax*sizeof (char *));
657
658 setpwent (); 632 setpwent ();
659 locative = noseeum_cons (Qnil, Qnil); 633 record_unwind_protect (user_name_completion_unwind, cache_incomplete_p);
660 XCAR (locative) = make_opaque_ptr ((void *) &cache); 634 while ((pwd = getpwent ()))
661 XCDR (locative) = make_opaque_ptr ((void *) &clen);
662 record_unwind_protect (user_name_completion_unwind, locative);
663 /* #### may need to slow down interrupts around call to getpwent
664 * below. at least the call to getpwnam in Fuser_full_name
665 * is documented as needing it on irix. */
666 while ((pw = getpwent ()))
667 { 635 {
668 if (clen >= cmax)
669 {
670 cmax *= 2;
671 cache = (char **) realloc (cache, cmax*sizeof (char *));
672 }
673
674 QUIT; 636 QUIT;
675 637 DO_REALLOC (user_cache.user_names, user_cache.size,
676 cache[clen++] = strdup (pw->pw_name); 638 user_cache.length + 1, struct user_name);
639 TO_INTERNAL_FORMAT (C_STRING, pwd->pw_name,
640 MALLOC,
641 (user_cache.user_names[user_cache.length].ptr,
642 user_cache.user_names[user_cache.length].len),
643 Qnative);
644 user_cache.length++;
677 } 645 }
678 free_opaque_ptr (XCAR (locative)); 646 XCAR (cache_incomplete_p) = Qnil;
679 free_opaque_ptr (XCDR (locative)); 647 unbind_to (speccount, Qnil);
680 XCAR (locative) = Qnil; 648
681 XCDR (locative) = Qnil; 649 EMACS_GET_TIME (user_cache.last_rebuild_time);
682 650 }
683 unbind_to (speccount, Qnil); /* free locative cons, endpwent() */ 651
684 652 for (i = 0; i < user_cache.length; i++)
685 user_cache_max = cmax; 653 {
686 user_cache_len = clen; 654 Bufbyte *u_name = user_cache.user_names[i].ptr;
687 user_cache = cache; 655 Bytecount len = user_cache.user_names[i].len;
688 user_cache_time = EMACS_SECS (t);
689 }
690
691 for (i = 0; i < user_cache_len; i++)
692 {
693 Bufbyte *d_name = (Bufbyte *) user_cache[i];
694 Bytecount len = strlen ((char *) d_name);
695 /* scmp() works in chars, not bytes, so we have to compute this: */ 656 /* scmp() works in chars, not bytes, so we have to compute this: */
696 Charcount cclen = bytecount_to_charcount (d_name, len); 657 Charcount cclen = bytecount_to_charcount (u_name, len);
697 658
698 QUIT; 659 QUIT;
699 660
700 if (cclen < user_name_length || 661 if (cclen < user_name_length
701 0 <= scmp (d_name, XSTRING_DATA (user), user_name_length)) 662 || 0 <= scmp_1 (u_name, XSTRING_DATA (user), user_name_length, 0))
702 continue; 663 continue;
703 664
704 matchcount++; /* count matching completions */ 665 matchcount++; /* count matching completions */
705 666
706 if (all_flag || NILP (bestmatch)) 667 if (all_flag || NILP (bestmatch))
707 { 668 {
708 Lisp_Object name = Qnil; 669 Lisp_Object name = Qnil;
709 struct gcpro ngcpro1; 670 struct gcpro ngcpro1;
710 NGCPRO1 (name); 671 NGCPRO1 (name);
711 /* This is a possible completion */ 672 /* This is a possible completion */
712 name = make_string (d_name, len); 673 name = make_string (u_name, len);
713 if (all_flag) 674 if (all_flag)
714 { 675 {
715 bestmatch = Fcons (name, bestmatch); 676 bestmatch = Fcons (name, bestmatch);
716 } 677 }
717 else 678 else
723 } 684 }
724 else 685 else
725 { 686 {
726 Charcount compare = min (bestmatchsize, cclen); 687 Charcount compare = min (bestmatchsize, cclen);
727 Bufbyte *p1 = XSTRING_DATA (bestmatch); 688 Bufbyte *p1 = XSTRING_DATA (bestmatch);
728 Bufbyte *p2 = d_name; 689 Bufbyte *p2 = u_name;
729 Charcount matchsize = scmp (p1, p2, compare); 690 Charcount matchsize = scmp_1 (p1, p2, compare, 0);
730 691
731 if (matchsize < 0) 692 if (matchsize < 0)
732 matchsize = compare; 693 matchsize = compare;
733 if (completion_ignore_case)
734 {
735 /* If this is an exact match except for case,
736 use it as the best match rather than one that is not
737 an exact match. This way, we get the case pattern
738 of the actual match. */
739 if ((matchsize == cclen
740 && matchsize < XSTRING_CHAR_LENGTH (bestmatch))
741 ||
742 /* If there is no exact match ignoring case,
743 prefer a match that does not change the case
744 of the input. */
745 (((matchsize == cclen)
746 ==
747 (matchsize == XSTRING_CHAR_LENGTH (bestmatch)))
748 /* If there is more than one exact match aside from
749 case, and one of them is exact including case,
750 prefer that one. */
751 && 0 > scmp_1 (p2, XSTRING_DATA (user),
752 user_name_length, 0)
753 && 0 <= scmp_1 (p1, XSTRING_DATA (user),
754 user_name_length, 0)))
755 {
756 bestmatch = make_string (d_name, len);
757 }
758 }
759 694
760 bestmatchsize = matchsize; 695 bestmatchsize = matchsize;
761 } 696 }
762 } 697 }
763 698
774 } 709 }
775 #endif /* ! defined WINDOWSNT */ 710 #endif /* ! defined WINDOWSNT */
776 711
777 712
778 Lisp_Object 713 Lisp_Object
779 make_directory_hash_table (CONST char *path) 714 make_directory_hash_table (const char *path)
780 { 715 {
781 DIR *d; 716 DIR *d;
782 Lisp_Object hash =
783 make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
784 if ((d = opendir (path))) 717 if ((d = opendir (path)))
785 { 718 {
786 DIRENTRY *dp; 719 DIRENTRY *dp;
720 Lisp_Object hash =
721 make_lisp_hash_table (20, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
787 722
788 while ((dp = readdir (d))) 723 while ((dp = readdir (d)))
789 { 724 {
790 Bytecount len = NAMLEN (dp); 725 Bytecount len = NAMLEN (dp);
791 if (DIRENTRY_NONEMPTY (dp)) 726 if (DIRENTRY_NONEMPTY (dp))
792 /* Cast to Bufbyte* is OK, as readdir() Mule-encapsulates. */ 727 /* Cast to Bufbyte* is OK, as readdir() Mule-encapsulates. */
793 Fputhash (make_string ((Bufbyte *) dp->d_name, len), Qt, hash); 728 Fputhash (make_string ((Bufbyte *) dp->d_name, len), Qt, hash);
794 } 729 }
795 closedir (d); 730 closedir (d);
796 } 731 return hash;
797 return hash; 732 }
733 else
734 return Qnil;
798 } 735 }
799 736
800 Lisp_Object 737 Lisp_Object
801 wasteful_word_to_lisp (unsigned int item) 738 wasteful_word_to_lisp (unsigned int item)
802 { 739 {
953 but does affect the commands that actually do completions. 890 but does affect the commands that actually do completions.
954 It is used by the functions `file-name-completion' and 891 It is used by the functions `file-name-completion' and
955 `file-name-all-completions'. 892 `file-name-all-completions'.
956 */ ); 893 */ );
957 Vcompletion_ignored_extensions = Qnil; 894 Vcompletion_ignored_extensions = Qnil;
958 895 }
959 #ifndef WINDOWSNT
960 user_cache = NULL;
961 user_cache_len = 0;
962 user_cache_max = 0;
963 #endif
964 }