Mercurial > emacs
comparison src/fileio.c @ 21684:89e327fdea93
(Fmake_temp_name): Complete rewrite.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Mon, 20 Apr 1998 18:13:03 +0000 |
parents | 55865851fd69 |
children | e02be2b47d18 |
comparison
equal
deleted
inserted
replaced
21683:dfb671ba22f8 | 21684:89e327fdea93 |
---|---|
788 #endif | 788 #endif |
789 directory_file_name (XSTRING (directory)->data, buf); | 789 directory_file_name (XSTRING (directory)->data, buf); |
790 return build_string (buf); | 790 return build_string (buf); |
791 } | 791 } |
792 | 792 |
793 static char make_temp_name_tbl[64] = | |
794 { | |
795 'A','B','C','D','E','F','G','H', | |
796 'I','J','K','L','M','N','O','P', | |
797 'Q','R','S','T','U','V','W','X', | |
798 'Y','Z','a','b','c','d','e','f', | |
799 'g','h','i','j','k','l','m','n', | |
800 'o','p','q','r','s','t','u','v', | |
801 'w','x','y','z','0','1','2','3', | |
802 '4','5','6','7','8','9','-','_' | |
803 }; | |
804 static unsigned make_temp_name_count, make_temp_name_count_initialized_p; | |
805 | |
793 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0, | 806 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0, |
794 "Generate temporary file name (string) starting with PREFIX (a string).\n\ | 807 "Generate temporary file name (string) starting with PREFIX (a string).\n\ |
795 The Emacs process number forms part of the result,\n\ | 808 The Emacs process number forms part of the result,\n\ |
796 so there is no danger of generating a name being used by another process.\n\ | 809 so there is no danger of generating a name being used by another process.\n\ |
810 \n\ | |
797 In addition, this function makes an attempt to choose a name\n\ | 811 In addition, this function makes an attempt to choose a name\n\ |
798 which has no existing file.") | 812 which has no existing file. To make this work,\n\ |
813 PREFIX should be an absolute file name.") | |
799 (prefix) | 814 (prefix) |
800 Lisp_Object prefix; | 815 Lisp_Object prefix; |
801 { | 816 { |
802 char *temp; | |
803 Lisp_Object val; | 817 Lisp_Object val; |
804 #ifdef MSDOS | 818 int len; |
805 /* Don't use too many characters of the restricted 8+3 DOS | 819 int pid; |
806 filename space. */ | 820 unsigned char *p, *data; |
807 val = concat2 (prefix, build_string ("a.XXX")); | 821 char pidbuf[20]; |
822 int pidlen; | |
823 | |
824 CHECK_STRING (prefix, 0); | |
825 | |
826 /* VAL is created by adding 6 characters to PREFIX. The first | |
827 three are the PID of this process, in base 64, and the second | |
828 three are incremented if the file already exists. This ensures | |
829 262144 unique file names per PID per PREFIX. */ | |
830 | |
831 pid = (int) getpid (); | |
832 | |
833 #ifdef HAVE_LONG_FILE_NAMES | |
834 sprintf (pidbuf, "%d", pid); | |
835 pidlen = strlen (pidbuf); | |
808 #else | 836 #else |
809 val = concat2 (prefix, build_string ("XXXXXX")); | 837 pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6; |
810 #endif | 838 pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6; |
811 temp = mktemp (XSTRING (val)->data); | 839 pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6; |
812 if (! temp) | 840 pidlen = 3; |
813 error ("No temporary file names based on %s are available", | 841 #endif |
814 XSTRING (prefix)->data); | 842 |
815 #ifdef DOS_NT | 843 len = XSTRING (prefix)->size; |
816 CORRECT_DIR_SEPS (XSTRING (val)->data); | 844 val = make_uninit_string (len + 3 + pidlen); |
817 #endif | 845 data = XSTRING (val)->data; |
818 return val; | 846 bcopy(XSTRING (prefix)->data, data, len); |
819 } | 847 p = data + len; |
848 | |
849 bcopy (pidbuf, p, pidlen); | |
850 p += pidlen; | |
851 | |
852 /* Here we try to minimize useless stat'ing when this function is | |
853 invoked many times successively with the same PREFIX. We achieve | |
854 this by initializing count to a random value, and incrementing it | |
855 afterwards. */ | |
856 if (!make_temp_name_count_initialized_p) | |
857 { | |
858 make_temp_name_count = (unsigned) time (NULL); | |
859 make_temp_name_count_initialized_p = 1; | |
860 } | |
861 | |
862 while (1) | |
863 { | |
864 struct stat ignored; | |
865 unsigned num = make_temp_name_count++; | |
866 | |
867 p[0] = make_temp_name_tbl[num & 63], num >>= 6; | |
868 p[1] = make_temp_name_tbl[num & 63], num >>= 6; | |
869 p[2] = make_temp_name_tbl[num & 63], num >>= 6; | |
870 | |
871 if (stat (data, &ignored) < 0) | |
872 { | |
873 /* We want to return only if errno is ENOENT. */ | |
874 if (errno == ENOENT) | |
875 return val; | |
876 else | |
877 /* The error here is dubious, but there is little else we | |
878 can do. The alternatives are to return nil, which is | |
879 as bad as (and in many cases worse than) throwing the | |
880 error, or to ignore the error, which will likely result | |
881 in looping through 262144 stat's, which is not only | |
882 SLOW, but also useless since it will fallback to the | |
883 errow below, anyway. */ | |
884 report_file_error ("Cannot create temporary name for prefix `%s'", | |
885 Fcons (prefix, Qnil)); | |
886 /* not reached */ | |
887 } | |
888 } | |
889 | |
890 error ("Cannot create temporary name for prefix `%s'", | |
891 XSTRING (prefix)->data); | |
892 return Qnil; | |
893 } | |
894 | |
820 | 895 |
821 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, | 896 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, |
822 "Convert filename NAME to absolute, and canonicalize it.\n\ | 897 "Convert filename NAME to absolute, and canonicalize it.\n\ |
823 Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative\n\ | 898 Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative\n\ |
824 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,\n\ | 899 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,\n\ |