static int lock_if_free (lock_info_type *clasher, register char *lfname) { while (lock_file_1 (lfname, 0) == 0) { int locker; if (errno != EEXIST) return -1; locker = current_lock_owner (clasher, lfname); if (locker == 2) { FREE_LOCK_INFO (*clasher); return 0; /* We ourselves locked it. */ } else if (locker == 1) return 1; /* Someone else has it. */ else if (locker == -1) return -1; /* current_lock_owner returned strange error. */ /* We deleted a stale lock; try again to lock the file. */ } return 0; }
void lock_file (Lisp_Object fn) { register Lisp_Object attack, orig_fn, encoded_fn; register char *lfname, *locker; lock_info_type lock_info; struct gcpro gcpro1; /* Don't do locking while dumping Emacs. Uncompressing wtmp files uses call-process, which does not work in an uninitialized Emacs. */ if (! NILP (Vpurify_flag)) return; orig_fn = fn; GCPRO1 (fn); fn = Fexpand_file_name (fn, Qnil); encoded_fn = ENCODE_FILE (fn); /* Create the name of the lock-file for file fn */ MAKE_LOCK_NAME (lfname, encoded_fn); /* See if this file is visited and has changed on disk since it was visited. */ { register Lisp_Object subject_buf; subject_buf = get_truename_buffer (orig_fn); if (!NILP (subject_buf) && NILP (Fverify_visited_file_modtime (subject_buf)) && !NILP (Ffile_exists_p (fn))) call1 (intern ("ask-user-about-supersession-threat"), fn); } UNGCPRO; /* Try to lock the lock. */ if (lock_if_free (&lock_info, lfname) <= 0) /* Return now if we have locked it, or if lock creation failed */ return; /* Else consider breaking the lock */ locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host) + LOCK_PID_MAX + 9); sprintf (locker, "%s@%s (pid %lu)", lock_info.user, lock_info.host, lock_info.pid); FREE_LOCK_INFO (lock_info); attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker)); if (!NILP (attack)) /* User says take the lock */ { lock_file_1 (lfname, 1); return; } /* User says ignore the lock */ }