diff lisp/efs/efs-cp-p.el @ 22:8fc7fe29b841 r19-15b94

Import from CVS: tag r19-15b94
author cvs
date Mon, 13 Aug 2007 08:50:29 +0200
parents
children 8b8b7f3559a2 8619ce7e4c50
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/efs/efs-cp-p.el	Mon Aug 13 08:50:29 2007 +0200
@@ -0,0 +1,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