Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
emacs
emacs
Commits
8489eb67
Commit
8489eb67
authored
Jan 14, 1991
by
Richard M. Stallman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial revision
parent
5aafeb12
Changes
2
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1575 additions
and
0 deletions
+1575
-0
src/filelock.c
src/filelock.c
+359
-0
src/syntax.c
src/syntax.c
+1216
-0
No files found.
src/filelock.c
0 → 100644
View file @
8489eb67
/* Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
#include <pwd.h>
#include <errno.h>
#include <sys/file.h>
#ifdef USG
#include <fcntl.h>
#endif
/* USG */
#undef NULL
#include "lisp.h"
#include "paths.h"
#include "buffer.h"
extern
int
errno
;
#ifdef CLASH_DETECTION
/* If system does not have symbolic links, it does not have lstat.
In that case, use ordinary stat instead. */
#ifndef S_IFLNK
#define lstat stat
#endif
static
Lisp_Object
lock_file_owner_name
(
lfname
)
char
*
lfname
;
{
struct
stat
s
;
struct
passwd
*
the_pw
;
extern
struct
passwd
*
getpwuid
();
if
(
lstat
(
lfname
,
&
s
)
==
0
)
the_pw
=
getpwuid
(
s
.
st_uid
);
return
(
the_pw
==
0
?
Qnil
:
build_string
(
the_pw
->
pw_name
));
}
/* lock_file locks file fn,
meaning it serves notice on the world that you intend to edit that file.
This should be done only when about to modify a file-visiting
buffer previously unmodified.
Do not (normally) call lock_buffer for a buffer already modified,
as either the file is already locked, or the user has already
decided to go ahead without locking.
When lock_buffer returns, either the lock is locked for us,
or the user has said to go ahead without locking.
If the file is locked by someone else, lock_buffer calls
ask-user-about-lock (a Lisp function) with two arguments,
the file name and the name of the user who did the locking.
This function can signal an error, or return t meaning
take away the lock, or return nil meaning ignore the lock. */
/* The lock file name is the file name with "/" replaced by "!"
and put in the Emacs lock directory. */
/* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
void
lock_file
(
fn
)
register
Lisp_Object
fn
;
{
register
Lisp_Object
attack
;
register
char
*
lfname
;
/* Create the name of the lock-file for file fn */
lfname
=
(
char
*
)
alloca
(
XSTRING
(
fn
)
->
size
+
strlen
(
PATH_LOCK
)
+
1
);
fill_in_lock_file_name
(
lfname
,
fn
);
/* See if this file is visited and has changed on disk since it was visited. */
{
register
Lisp_Object
subject_buf
=
Fget_file_buffer
(
fn
);
if
(
!
NULL
(
subject_buf
)
&&
NULL
(
Fverify_visited_file_modtime
(
subject_buf
))
&&
!
NULL
(
Ffile_exists_p
(
fn
)))
call1
(
intern
(
"ask-user-about-supersession-threat"
),
fn
);
}
/* Try to lock the lock. */
if
(
lock_if_free
(
lfname
)
<=
0
)
/* Return now if we have locked it, or if lock dir does not exist */
return
;
/* Else consider breaking the lock */
attack
=
call2
(
intern
(
"ask-user-about-lock"
),
fn
,
lock_file_owner_name
(
lfname
));
if
(
!
NULL
(
attack
))
/* User says take the lock */
{
lock_superlock
(
lfname
);
lock_file_1
(
lfname
,
O_WRONLY
)
;
unlink
(
PATH_SUPERLOCK
);
return
;
}
/* User says ignore the lock */
}
fill_in_lock_file_name
(
lockfile
,
fn
)
register
char
*
lockfile
;
register
Lisp_Object
fn
;
{
register
char
*
p
;
strcpy
(
lockfile
,
PATH_LOCK
);
p
=
lockfile
+
strlen
(
lockfile
);
strcpy
(
p
,
XSTRING
(
fn
)
->
data
);
for
(;
*
p
;
p
++
)
{
if
(
*
p
==
'/'
)
*
p
=
'!'
;
}
}
/* Lock the lock file named LFNAME.
If MODE is O_WRONLY, we do so even if it is already locked.
If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free.
Return 1 if successful, 0 if not. */
int
lock_file_1
(
lfname
,
mode
)
int
mode
;
char
*
lfname
;
{
register
int
fd
;
char
buf
[
20
];
if
((
fd
=
open
(
lfname
,
mode
,
0666
))
>=
0
)
{
#ifdef USG
chmod
(
lfname
,
0666
);
#else
fchmod
(
fd
,
0666
);
#endif
sprintf
(
buf
,
"%d "
,
getpid
());
write
(
fd
,
buf
,
strlen
(
buf
));
close
(
fd
);
return
1
;
}
else
return
0
;
}
/* Lock the lock named LFNAME if possible.
Return 0 in that case.
Return positive if lock is really locked by someone else.
Return -1 if cannot lock for any other reason. */
int
lock_if_free
(
lfname
)
register
char
*
lfname
;
{
register
int
clasher
;
while
(
lock_file_1
(
lfname
,
O_WRONLY
|
O_EXCL
|
O_CREAT
)
==
0
)
{
if
(
errno
!=
EEXIST
)
return
-
1
;
clasher
=
current_lock_owner
(
lfname
);
if
(
clasher
!=
0
)
if
(
clasher
!=
getpid
())
return
(
clasher
);
else
return
(
0
);
/* Try again to lock it */
}
return
0
;
}
/* Return the pid of the process that claims to own the lock file LFNAME,
or 0 if nobody does or the lock is obsolete,
or -1 if something is wrong with the locking mechanism. */
int
current_lock_owner
(
lfname
)
char
*
lfname
;
{
int
owner
=
current_lock_owner_1
(
lfname
);
if
(
owner
==
0
&&
errno
==
ENOENT
)
return
(
0
);
/* Is it locked by a process that exists? */
if
(
owner
!=
0
&&
(
kill
(
owner
,
0
)
>=
0
||
errno
==
EPERM
))
return
(
owner
);
if
(
unlink
(
lfname
)
<
0
)
return
(
-
1
);
return
(
0
);
}
int
current_lock_owner_1
(
lfname
)
char
*
lfname
;
{
register
int
fd
;
char
buf
[
20
];
int
tem
;
fd
=
open
(
lfname
,
O_RDONLY
,
0666
);
if
(
fd
<
0
)
return
0
;
tem
=
read
(
fd
,
buf
,
sizeof
buf
);
close
(
fd
);
return
(
tem
<=
0
?
0
:
atoi
(
buf
));
}
void
unlock_file
(
fn
)
register
Lisp_Object
fn
;
{
register
char
*
lfname
;
lfname
=
(
char
*
)
alloca
(
XSTRING
(
fn
)
->
size
+
strlen
(
PATH_LOCK
)
+
1
);
fill_in_lock_file_name
(
lfname
,
fn
);
lock_superlock
(
lfname
);
if
(
current_lock_owner_1
(
lfname
)
==
getpid
())
unlink
(
lfname
);
unlink
(
PATH_SUPERLOCK
);
}
lock_superlock
(
lfname
)
char
*
lfname
;
{
register
int
i
,
fd
;
for
(
i
=
-
20
;
i
<
0
&&
(
fd
=
open
(
PATH_SUPERLOCK
,
O_WRONLY
|
O_EXCL
|
O_CREAT
,
0666
))
<
0
;
i
++
)
{
if
(
errno
!=
EEXIST
)
return
;
sleep
(
1
);
}
if
(
fd
>=
0
)
{
#ifdef USG
chmod
(
PATH_SUPERLOCK
,
0666
);
#else
fchmod
(
fd
,
0666
);
#endif
write
(
fd
,
lfname
,
strlen
(
lfname
));
close
(
fd
);
}
}
void
unlock_all_files
()
{
register
Lisp_Object
tail
;
register
struct
buffer
*
b
;
for
(
tail
=
Vbuffer_alist
;
XGCTYPE
(
tail
)
==
Lisp_Cons
;
tail
=
XCONS
(
tail
)
->
cdr
)
{
b
=
XBUFFER
(
XCONS
(
XCONS
(
tail
)
->
car
)
->
cdr
);
if
(
XTYPE
(
b
->
filename
)
==
Lisp_String
&&
b
->
save_modified
<
BUF_MODIFF
(
b
))
unlock_file
(
b
->
filename
);
}
}
DEFUN
(
"lock-buffer"
,
Flock_buffer
,
Slock_buffer
,
0
,
1
,
0
,
"Lock FILE, if current buffer is modified.
\n
\
FILE defaults to current buffer's visited file,
\n
\
or else nothing is done if current buffer isn't visiting a file."
)
(
fn
)
Lisp_Object
fn
;
{
if
(
NULL
(
fn
))
fn
=
current_buffer
->
filename
;
else
CHECK_STRING
(
fn
,
0
);
if
(
current_buffer
->
save_modified
<
MODIFF
&&
!
NULL
(
fn
))
lock_file
(
fn
);
return
Qnil
;
}
DEFUN
(
"unlock-buffer"
,
Funlock_buffer
,
Sunlock_buffer
,
0
,
0
,
0
,
"Unlock the file visited in the current buffer,
\n
\
if it should normally be locked."
)
()
{
if
(
current_buffer
->
save_modified
<
MODIFF
&&
XTYPE
(
current_buffer
->
filename
)
==
Lisp_String
)
unlock_file
(
current_buffer
->
filename
);
return
Qnil
;
}
/* Unlock the file visited in buffer BUFFER. */
unlock_buffer
(
buffer
)
struct
buffer
*
buffer
;
{
if
(
buffer
->
save_modified
<
BUF_MODIFF
(
buffer
)
&&
XTYPE
(
buffer
->
filename
)
==
Lisp_String
)
unlock_file
(
buffer
->
filename
);
}
DEFUN
(
"file-locked-p"
,
Ffile_locked_p
,
Sfile_locked_p
,
0
,
1
,
0
,
"Return nil if the FILENAME is not locked,
\n
\
t if it is locked by you, else a string of the name of the locker."
)
(
fn
)
Lisp_Object
fn
;
{
register
char
*
lfname
;
int
owner
;
fn
=
Fexpand_file_name
(
fn
,
Qnil
);
/* Create the name of the lock-file for file filename */
lfname
=
(
char
*
)
alloca
(
XSTRING
(
fn
)
->
size
+
strlen
(
PATH_LOCK
)
+
1
);
fill_in_lock_file_name
(
lfname
,
fn
);
owner
=
current_lock_owner
(
lfname
);
if
(
owner
<=
0
)
return
(
Qnil
);
else
if
(
owner
==
getpid
())
return
(
Qt
);
return
(
lock_file_owner_name
(
lfname
));
}
syms_of_filelock
()
{
defsubr
(
&
Sunlock_buffer
);
defsubr
(
&
Slock_buffer
);
defsubr
(
&
Sfile_locked_p
);
}
#endif
/* CLASH_DETECTION */
src/syntax.c
0 → 100644
View file @
8489eb67
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment