1 /*
2 Licensed under the GNU Public License.
3 Copyright (C) 1998-2009 by Thomas M. Vier, Jr. All Rights Reserved.
4
5 wipe is free software.
6 See LICENSE for more information.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include <unistd.h>
24 #include <stdio.h>
25
26 #include "config.h"
27
28 #ifdef HAVE_FCNTL_H
29 # include <fcntl.h>
30 #else
31 # undef HAVE_FCNTL
32 #endif
33
34 #include <sys/types.h>
35 #include <sys/stat.h>
36
37 #ifndef HAVE_FCNTL
38 # ifndef HAVE_LOCKF
39 # ifdef HAVE_FLOCK
40 # ifdef HAVE_SYS_FILE_H
41 # include <sys/file.h>
42 # else
43 # undef HAVE_FLOCK
44 # endif
45 # endif
46 # endif
47 #endif
48
49 #undef LOCKABLE
50 #ifdef HAVE_FCNTL
51 # define LOCKABLE
52 #elif HAVE_LOCKF
53 # define LOCKABLE
54 #elif HAVE_FLOCK
55 # define LOCKABLE
56 #endif
57
58 #include "std.h"
59 #include "main.h"
60 #include "percent.h"
61 #include "file.h"
62 #include "lock.h"
63
64 extern char *argvzero;
65 extern struct opt_s options;
66
67 /*
68 lock -- create as good a lock as possible
69 what a mess
70 */
71
do_lock(struct file_s * f)72 public int do_lock(struct file_s *f)
73 {
74 char prompt[4];
75
76 #ifndef LOCKABLE
77 return(0);
78 #endif
79
80 #ifdef HAVE_FCNTL
81 struct flock file_lock;
82
83 file_lock.l_type = F_WRLCK;
84 file_lock.l_whence = 0;
85 file_lock.l_start = 0;
86 file_lock.l_len = 0;
87 #endif
88
89 #ifdef LOCKTEST
90 fprintf(stderr, "\rattempting lock on %s...", f->name);
91 #endif
92
93 #ifdef HAVE_FCHMOD
94 /* try for a mandatory lock */
95 if (fchmod(f->fd, 02600))
96 {
97 # ifdef LOCKTEST
98 fprintf(stderr, "mandatory lock failed\ntrying for advisory...");
99 # endif
100 }
101 #endif
102
103 #ifdef HAVE_FCNTL
104 if (fcntl(f->fd, F_SETLKW, &file_lock) == 0)
105 {
106 # ifdef LOCKTEST
107 fprintf(stderr, "got it\n");
108 # endif
109 return 0; /* lock successful */
110 }
111
112 #elif HAVE_LOCKF
113
114 if (lseek(f->fd, 0, SEEK_SET))
115 {
116 fprintf(stderr, "\r%s: lseek() failed for `%s': %s\n",
117 argvzero, name, strerror(errno));
118 exit_code = errno; return FAILED;
119 }
120
121 if (lockf(f->fd, F_LOCK, f->fsize) == 0)
122 {
123 # ifdef LOCKTEST
124 fprintf(stderr, "got it\n");
125 # endif
126 return 0; /* lock successful */
127 }
128
129 #elif HAVE_FLOCK
130 if (flock(f->fd, LOCK_EX) == 0)
131 {
132 # ifdef LOCKTEST
133 fprintf(stderr, "got it\n");
134 # endif
135 return 0; /* lock successful */
136 }
137 #endif
138
139 /* lock failed */
140 if (options.force && !options.verbose)
141 return 0;
142
143 prompt[0] = 0; /* clear prompt */
144 while (prompt[0] != 'y' && prompt[0] != 'n')
145 {
146 printf("\r%s: lock failed: \'%s\'. Wipe anyway? ", argvzero, f->name);
147 fgets(prompt, sizeof(prompt), stdin);
148
149 if (prompt[0] == 'y') return 0;
150 if (prompt[0] == 'n') return FAILED;
151 }
152
153 return 0;
154 }
155