File: efs-cp-p.el

package info (click to toggle)
xemacs20 20.4-13
  • links: PTS
  • area: main
  • in suites: slink
  • size: 67,324 kB
  • ctags: 57,643
  • sloc: lisp: 586,197; ansic: 184,662; sh: 4,296; asm: 3,179; makefile: 2,021; perl: 1,059; csh: 96; sed: 22
file content (165 lines) | stat: -rw-r--r-- 5,049 bytes parent folder | download | duplicates (3)
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
;; -*-Emacs-Lisp-*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; File:         efs-cp-p.el
;; Release:      $efs release: 1.15 $
;; Version:      #Revision: 1.1 $
;; RCS:          
;; Description:  Support for preserving file modtimes with copies. i.e. cp -p
;; Author:       Sandy Rutherford <sandy@ibm550.sissa.it>
;; Created:      Fri Feb 18 03:28:22 1994 by sandy on ibm550
;; Modified:     Sun Nov 27 12:17:33 1994 by sandy on gandalf
;; Language:     Emacs-Lisp
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; This file is part of efs. See efs.el for copyright
;;; (it's copylefted) and warrranty (there isn't one) information.

(provide 'efs-cp-p)
(require 'efs)

;;;; Internal Variables

(defconst efs-cp-p-version
  (concat (substring "$efs release: 1.15 $" 14 -2)
	  "/"
	  (substring "#Revision: 1.1 $" 11 -2)))

(defvar efs-local-timezone nil)
;; cache.

;;; Utility functions

(efs-define-fun efs-gmt-time ()
  ;; Get the time as the number of seconds elapsed since midnight,
  ;; Jan 1, 1970, GMT.  Emacs 18 doesn't have `current-time' function.
  (let ((time (current-time)))
    (list (car time) (nth 1 time))))

(defun efs-local-time ()
  (let ((str (current-time-string)))
    (efs-seconds-elapsed
     (string-to-int (substring str -4))
     (cdr (assoc (substring str 4 7) efs-month-alist))
     (string-to-int (substring str 8 10))
     (string-to-int (substring str 11 13))
     (string-to-int (substring str 14 16))
     0))) ; don't care about seconds
   
(defun efs-local-timezone ()
  ;; Returns the local timezone as an integer. Right two digits the minutes,
  ;; others the hours.
  (or efs-local-timezone
      (setq efs-local-timezone
	    (let* ((local (efs-local-time))
		   (gmt (efs-gmt-time))
		   (sign 1)
		   (diff (efs-time-minus local gmt))
		   hours minutes)
	      ;; 2^16 is 36 hours.
	      (if (zerop (car diff))
		  (setq diff (nth 1 diff))
		(error "Weird timezone!"))
	      (setq diff (/ (- (nth 1 local) (nth 1 gmt)) 60))
	      (setq hours (/ diff 60))
	      (setq minutes (% diff 60))
	      (if (< diff 0)
		  (setq sign -1
			hours (- hours)
			minutes (- minutes)))
	      ;; Round minutes
	      (setq minutes (* 10 (/ (+ minutes 5) 10)))
	      (if (= minutes 60)
		  (setq hours (1+ hours)
			minutes 0))
	      (* sign (+ (* hours 100) minutes))))))
	    
(defun efs-last-day-of-month (month year)
  ;; The last day in MONTH during YEAR.
  ;; Taken from calendar.el. Thanks.
  (if (and
       (or
	(and (=  (% year   4) 0)
	     (/= (% year 100) 0))  ; leap-year-p
	(= (% year 400) 0))
       (= month 2))
      29
    (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month))))

(defun efs-make-date-local (year month day hour minutes seconds)
  ;; Takes a GMT date (list of integers), and returns the local time.
  (let* ((lzone (efs-local-timezone))
	 (lminutes (% lzone 100))
	 (lhour (/ lzone 100)))
    (setq minutes (+ minutes lminutes))
    (cond ((> minutes 60)
	   (setq minutes (- minutes 60)
		 hour (1+ hour)))
	  ((< minutes 0)
	   (setq minutes (+ minutes 60)
		 hour (1- hour))))
    (setq hour (+ lhour hour))
    (if (or (< hour 0) (> hour 23))
	(progn
	  (cond ((< hour 0)
		 (setq hour (+ hour 24)
		       day (1- day)))
		((> hour 23)
		 (setq hour (- hour 24)
		       day (1+ day))))
	  (if (or (zerop day) (> day
				 (efs-last-day-of-month month year)))
	      (cond ((zerop day)
		     (setq month (1- month))
		     (if (zerop month)
			 (setq year (1- year)
			       month 12))
		     (setq day (efs-last-day-of-month month year)))
		    ((> day (efs-last-day-of-month month year))
		     (setq month (1+ month)
			   day 1)
		     (if (= month 13)
			 (setq year (1+ year)
			       month 1)))))))
    (list year month day hour minutes seconds)))

;;;; Entry function

(defun efs-set-mdtm-of (filename newname &optional cont)
  ;; NEWNAME must be local
  ;; Always works NOWAIT = 0
  (let* ((parsed (efs-ftp-path filename))
	 (host (car parsed))
	 (user (nth 1 parsed))
	 (file (nth 2 parsed)))
    (if (efs-get-host-property host 'mdtm-failed)
	(and cont (efs-call-cont cont 'failed "" "") nil)
      (efs-send-cmd
       host user
       (list 'quote 'mdtm file)
       nil nil
       (efs-cont (result line cont-lines) (host newname cont)
	 (if (or result
		 (not (string-match efs-mdtm-msgs line)))
	     (efs-set-host-property host 'mdtm-failed t)
	   (let ((time (apply 'efs-make-date-local
			      (mapcar 'string-to-int
				      (list
				       (substring line 4 8)
				       (substring line 8 10)
				       (substring line 10 12)
				       (substring line 12 14)
				       (substring line 14 16)
				       (substring line 16 18))))))
	     (if time
		 (call-process "touch" nil 0 nil "-t"
			       (format "%04d%02d%02d%02d%02d.%02d"
				       (car time) (nth 1 time)
				       (nth 2 time) (nth 3 time)
				       (nth 4 time) (nth 5 time))
			       newname))))
	 (if cont (efs-call-cont cont result line cont-lines)))
       0))))

;;; end of efs-cp-p.el