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