]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/cdromutl.cc
* apt-pkg/contrib/fileutils.h:
[apt.git] / apt-pkg / contrib / cdromutl.cc
CommitLineData
d669751b
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b2e465d6 3// $Id: cdromutl.cc,v 1.12 2001/02/20 07:03:17 jgg Exp $
d669751b
AL
4/* ######################################################################
5
6 CDROM Utilities - Some functions to manipulate CDROM mounts.
7
8 These are here for the cdrom method and apt-cdrom.
9
10 ##################################################################### */
11 /*}}}*/
12// Include Files /*{{{*/
ea542140
DK
13#include<config.h>
14
d669751b
AL
15#include <apt-pkg/cdromutl.h>
16#include <apt-pkg/error.h>
17#include <apt-pkg/md5.h>
18#include <apt-pkg/fileutl.h>
6c907975 19#include <apt-pkg/configuration.h>
ef381816 20#include <apt-pkg/strutl.h>
d669751b
AL
21
22#include <sys/wait.h>
101030ab 23#include <sys/statvfs.h>
d669751b
AL
24#include <dirent.h>
25#include <fcntl.h>
4df0b629 26#include <sys/stat.h>
d669751b
AL
27#include <unistd.h>
28#include <stdio.h>
ea542140
DK
29
30#include <apti18n.h>
d669751b
AL
31 /*}}}*/
32
8f3ba4e8
DK
33using std::string;
34
6c907975 35// IsMounted - Returns true if the mount point is mounted /*{{{*/
d669751b 36// ---------------------------------------------------------------------
6c907975
AL
37/* This is a simple algorithm that should always work, we stat the mount point
38 and the '..' file in the mount point and see if they are on the same device.
39 By definition if they are the same then it is not mounted. This should
40 account for symlinked mount points as well. */
41bool IsMounted(string &Path)
d669751b 42{
4df0b629
AL
43 if (Path.empty() == true)
44 return false;
45
46 // Need that trailing slash for directories
47 if (Path[Path.length() - 1] != '/')
48 Path += '/';
49
50 /* First we check if the path is actualy mounted, we do this by
51 stating the path and the previous directory (carefull of links!)
52 and comparing their device fields. */
53 struct stat Buf,Buf2;
54 if (stat(Path.c_str(),&Buf) != 0 ||
55 stat((Path + "../").c_str(),&Buf2) != 0)
b2e465d6 56 return _error->Errno("stat",_("Unable to stat the mount point %s"),Path.c_str());
4df0b629
AL
57
58 if (Buf.st_dev == Buf2.st_dev)
6c907975
AL
59 return false;
60 return true;
61}
62 /*}}}*/
63// UnmountCdrom - Unmount a cdrom /*{{{*/
64// ---------------------------------------------------------------------
65/* Forking umount works much better than the umount syscall which can
66 leave /etc/mtab inconsitant. We drop all messages this produces. */
67bool UnmountCdrom(string Path)
68{
69 if (IsMounted(Path) == false)
4df0b629 70 return true;
d669751b 71
5ae004ce 72 for (int i=0;i<3;i++)
d669751b 73 {
5ae004ce
MV
74
75 int Child = ExecFork();
d669751b 76
5ae004ce
MV
77 // The child
78 if (Child == 0)
6c907975 79 {
5ae004ce
MV
80 // Make all the fds /dev/null
81 for (int I = 0; I != 3; I++)
82 dup2(open("/dev/null",O_RDWR),I);
83
84 if (_config->Exists("Acquire::cdrom::"+Path+"::UMount") == true)
85 {
86 if (system(_config->Find("Acquire::cdrom::"+Path+"::UMount").c_str()) != 0)
87 _exit(100);
88 _exit(0);
89 }
90 else
91 {
92 const char *Args[10];
93 Args[0] = "umount";
94 Args[1] = Path.c_str();
95 Args[2] = 0;
96 execvp(Args[0],(char **)Args);
6c907975 97 _exit(100);
5ae004ce 98 }
6c907975 99 }
5ae004ce
MV
100
101 // if it can not be umounted, give it a bit more time
102 // this can happen when auto-mount magic or fs/cdrom prober attack
103 if (ExecWait(Child,"umount",true) == true)
104 return true;
105 sleep(1);
d669751b
AL
106 }
107
5ae004ce 108 return false;
d669751b
AL
109}
110 /*}}}*/
111// MountCdrom - Mount a cdrom /*{{{*/
112// ---------------------------------------------------------------------
113/* We fork mount and drop all messages */
a6418a4b 114bool MountCdrom(string Path, string DeviceName)
d669751b 115{
6c907975
AL
116 if (IsMounted(Path) == true)
117 return true;
118
54676e1a 119 int Child = ExecFork();
d669751b
AL
120
121 // The child
122 if (Child == 0)
123 {
124 // Make all the fds /dev/null
d669751b
AL
125 for (int I = 0; I != 3; I++)
126 dup2(open("/dev/null",O_RDWR),I);
127
6c907975
AL
128 if (_config->Exists("Acquire::cdrom::"+Path+"::Mount") == true)
129 {
130 if (system(_config->Find("Acquire::cdrom::"+Path+"::Mount").c_str()) != 0)
131 _exit(100);
132 _exit(0);
133 }
134 else
135 {
136 const char *Args[10];
137 Args[0] = "mount";
a6418a4b
MV
138 if (DeviceName == "")
139 {
140 Args[1] = Path.c_str();
141 Args[2] = 0;
142 } else {
143 Args[1] = DeviceName.c_str();
144 Args[2] = Path.c_str();
145 Args[3] = 0;
146 }
6c907975
AL
147 execvp(Args[0],(char **)Args);
148 _exit(100);
149 }
d669751b
AL
150 }
151
152 // Wait for mount
ddc1d8d0 153 return ExecWait(Child,"mount",true);
d669751b
AL
154}
155 /*}}}*/
156// IdentCdrom - Generate a unique string for this CD /*{{{*/
157// ---------------------------------------------------------------------
158/* We convert everything we hash into a string, this prevents byte size/order
159 from effecting the outcome. */
34fc0421 160bool IdentCdrom(string CD,string &Res,unsigned int Version)
d669751b
AL
161{
162 MD5Summation Hash;
4dc7b4a7 163 bool writable_media = false;
d669751b 164
2a001232
MV
165 // if we are on a writable medium (like a usb-stick) that is just
166 // used like a cdrom don't use "." as it will constantly change,
167 // use .disk instead
4dc7b4a7
MV
168 if (access(CD.c_str(), W_OK) == 0 && DirectoryExists(CD+string("/.disk")))
169 {
170 writable_media = true;
7970157f 171 CD = CD.append("/.disk");
2a001232 172 if (_config->FindB("Debug::aptcdrom",false) == true)
7970157f
MV
173 std::clog << "Found writable cdrom, using alternative path: " << CD
174 << std::endl;
2a001232
MV
175 }
176
d669751b
AL
177 string StartDir = SafeGetCWD();
178 if (chdir(CD.c_str()) != 0)
b2e465d6 179 return _error->Errno("chdir",_("Unable to change to %s"),CD.c_str());
d669751b
AL
180
181 DIR *D = opendir(".");
182 if (D == 0)
b2e465d6 183 return _error->Errno("opendir",_("Unable to read %s"),CD.c_str());
d669751b 184
4df0b629
AL
185 /* Run over the directory, we assume that the reader order will never
186 change as the media is read-only. In theory if the kernel did
187 some sort of wacked caching this might not be true.. */
d669751b
AL
188 char S[300];
189 for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
190 {
191 // Skip some files..
192 if (strcmp(Dir->d_name,".") == 0 ||
193 strcmp(Dir->d_name,"..") == 0)
194 continue;
34fc0421
AL
195
196 if (Version <= 1)
197 {
0f297e46 198 sprintf(S,"%lu",(unsigned long)Dir->d_ino);
34fc0421
AL
199 }
200 else
201 {
202 struct stat Buf;
203 if (stat(Dir->d_name,&Buf) != 0)
204 continue;
1ae93c94 205 sprintf(S,"%lu",(unsigned long)Buf.st_mtime);
34fc0421
AL
206 }
207
d669751b
AL
208 Hash.Add(S);
209 Hash.Add(Dir->d_name);
210 };
211
6070a346
DK
212 if (chdir(StartDir.c_str()) != 0) {
213 _error->Errno("chdir",_("Unable to change to %s"),StartDir.c_str());
214 closedir(D);
215 return false;
216 }
d669751b
AL
217 closedir(D);
218
219 // Some stats from the fsys
fbdccabb
AL
220 if (_config->FindB("Debug::identcdrom",false) == false)
221 {
101030ab
AL
222 struct statvfs Buf;
223 if (statvfs(CD.c_str(),&Buf) != 0)
b2e465d6 224 return _error->Errno("statfs",_("Failed to stat the cdrom"));
4dc7b4a7 225
fbdccabb 226 // We use a kilobyte block size to advoid overflow
4dc7b4a7
MV
227 if (writable_media)
228 {
229 sprintf(S,"%lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)));
230 } else {
231 sprintf(S,"%lu %lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)),
232 (long)(Buf.f_bfree*(Buf.f_bsize/1024)));
233 }
fbdccabb
AL
234 Hash.Add(S);
235 sprintf(S,"-%u",Version);
236 }
237 else
238 sprintf(S,"-%u.debug",Version);
d669751b 239
34fc0421 240 Res = Hash.Result().Value() + S;
d669751b
AL
241 return true;
242}
243 /*}}}*/
ef381816 244
6070a346 245// FindMountPointForDevice - Find mountpoint for the given device /*{{{*/
02aa6f67 246string FindMountPointForDevice(const char *devnode)
ef381816
MV
247{
248 char buf[255];
249 char *out[10];
250 int i=0;
251
252 // this is the order that mount uses as well
253 const char *mount[] = { "/etc/mtab",
254 "/proc/mount",
255 NULL };
256
257 for (i=0; mount[i] != NULL; i++) {
258 if (FileExists(mount[i])) {
259 FILE *f=fopen(mount[i], "r");
260 while ( fgets(buf, sizeof(buf), f) != NULL) {
261 if (strncmp(buf, devnode, strlen(devnode)) == 0) {
262 if(TokSplitString(' ', buf, out, 10))
6070a346
DK
263 {
264 fclose(f);
a513ace2 265 // unescape the \0XXX chars in the path
f748b476 266 string mount_point = out[1];
a513ace2 267 return DeEscapeString(mount_point);
6070a346 268 }
ef381816
MV
269 }
270 }
271 fclose(f);
272 }
273 }
274
02aa6f67 275 return string();
ef381816 276}
6070a346 277 /*}}}*/