]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/cdromutl.cc
f850e08a5ff7c7c395e9e9c70af8b9a9f41ab04b
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: cdromutl.cc,v 1.12 2001/02/20 07:03:17 jgg Exp $
4 /* ######################################################################
6 CDROM Utilities - Some functions to manipulate CDROM mounts.
8 These are here for the cdrom method and apt-cdrom.
10 ##################################################################### */
12 // Include Files /*{{{*/
15 #include <apt-pkg/cdromutl.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/md5.h>
18 #include <apt-pkg/fileutl.h>
19 #include <apt-pkg/configuration.h>
20 #include <apt-pkg/strutl.h>
26 #include <sys/statvfs.h>
38 // IsMounted - Returns true if the mount point is mounted /*{{{*/
39 // ---------------------------------------------------------------------
40 /* This is a simple algorithm that should always work, we stat the mount point
41 and the '..' file in the mount point and see if they are on the same device.
42 By definition if they are the same then it is not mounted. This should
43 account for symlinked mount points as well. */
44 bool IsMounted(string
&Path
)
46 if (Path
.empty() == true)
49 // Need that trailing slash for directories
50 if (Path
[Path
.length() - 1] != '/')
53 // if the path has a ".disk" directory we treat it as mounted
54 // this way even extracted copies of disks are recognized
55 if (DirectoryExists(Path
+ ".disk/") == true)
58 /* First we check if the path is actually mounted, we do this by
59 stating the path and the previous directory (careful of links!)
60 and comparing their device fields. */
62 if (stat(Path
.c_str(),&Buf
) != 0 ||
63 stat((Path
+ "../").c_str(),&Buf2
) != 0)
64 return _error
->Errno("stat",_("Unable to stat the mount point %s"),Path
.c_str());
66 if (Buf
.st_dev
== Buf2
.st_dev
)
71 // UnmountCdrom - Unmount a cdrom /*{{{*/
72 // ---------------------------------------------------------------------
73 /* Forking umount works much better than the umount syscall which can
74 leave /etc/mtab inconsitant. We drop all messages this produces. */
75 bool UnmountCdrom(string Path
)
77 // do not generate errors, even if the mountpoint does not exist
78 // the mountpoint might be auto-created by the mount command
79 // and a non-existing mountpoint is surely not mounted
80 _error
->PushToStack();
81 bool const mounted
= IsMounted(Path
);
82 _error
->RevertToStack();
89 int Child
= ExecFork();
94 // Make all the fds /dev/null
95 int const null_fd
= open("/dev/null",O_RDWR
);
96 for (int I
= 0; I
!= 3; ++I
)
99 if (_config
->Exists("Acquire::cdrom::"+Path
+"::UMount") == true)
101 if (system(_config
->Find("Acquire::cdrom::"+Path
+"::UMount").c_str()) != 0)
107 const char *Args
[10];
109 Args
[1] = Path
.c_str();
111 execvp(Args
[0],(char **)Args
);
116 // if it can not be umounted, give it a bit more time
117 // this can happen when auto-mount magic or fs/cdrom prober attack
118 if (ExecWait(Child
,"umount",true) == true)
126 // MountCdrom - Mount a cdrom /*{{{*/
127 // ---------------------------------------------------------------------
128 /* We fork mount and drop all messages */
129 bool MountCdrom(string Path
, string DeviceName
)
131 // do not generate errors, even if the mountpoint does not exist
132 // the mountpoint might be auto-created by the mount command
133 _error
->PushToStack();
134 bool const mounted
= IsMounted(Path
);
135 _error
->RevertToStack();
139 int Child
= ExecFork();
144 // Make all the fds /dev/null
145 int const null_fd
= open("/dev/null",O_RDWR
);
146 for (int I
= 0; I
!= 3; ++I
)
149 if (_config
->Exists("Acquire::cdrom::"+Path
+"::Mount") == true)
151 if (system(_config
->Find("Acquire::cdrom::"+Path
+"::Mount").c_str()) != 0)
157 const char *Args
[10];
159 if (DeviceName
== "")
161 Args
[1] = Path
.c_str();
164 Args
[1] = DeviceName
.c_str();
165 Args
[2] = Path
.c_str();
168 execvp(Args
[0],(char **)Args
);
174 return ExecWait(Child
,"mount",true);
177 // IdentCdrom - Generate a unique string for this CD /*{{{*/
178 // ---------------------------------------------------------------------
179 /* We convert everything we hash into a string, this prevents byte size/order
180 from effecting the outcome. */
181 bool IdentCdrom(string CD
,string
&Res
,unsigned int Version
)
184 bool writable_media
= false;
186 // if we are on a writable medium (like a usb-stick) that is just
187 // used like a cdrom don't use "." as it will constantly change,
189 if (access(CD
.c_str(), W_OK
) == 0 && DirectoryExists(CD
+string("/.disk")))
191 writable_media
= true;
192 CD
= CD
.append("/.disk");
193 if (_config
->FindB("Debug::aptcdrom",false) == true)
194 std::clog
<< "Found writable cdrom, using alternative path: " << CD
198 string StartDir
= SafeGetCWD();
199 if (chdir(CD
.c_str()) != 0)
200 return _error
->Errno("chdir",_("Unable to change to %s"),CD
.c_str());
202 DIR *D
= opendir(".");
204 return _error
->Errno("opendir",_("Unable to read %s"),CD
.c_str());
206 /* Run over the directory, we assume that the reader order will never
207 change as the media is read-only. In theory if the kernel did
208 some sort of wacked caching this might not be true.. */
210 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
213 if (strcmp(Dir
->d_name
,".") == 0 ||
214 strcmp(Dir
->d_name
,"..") == 0)
219 sprintf(S
,"%lu",(unsigned long)Dir
->d_ino
);
224 if (stat(Dir
->d_name
,&Buf
) != 0)
226 sprintf(S
,"%lu",(unsigned long)Buf
.st_mtime
);
230 Hash
.Add(Dir
->d_name
);
233 if (chdir(StartDir
.c_str()) != 0) {
234 _error
->Errno("chdir",_("Unable to change to %s"),StartDir
.c_str());
240 // Some stats from the fsys
241 if (_config
->FindB("Debug::identcdrom",false) == false)
244 if (statvfs(CD
.c_str(),&Buf
) != 0)
245 return _error
->Errno("statfs",_("Failed to stat the cdrom"));
247 // We use a kilobyte block size to advoid overflow
250 sprintf(S
,"%lu",(long)(Buf
.f_blocks
*(Buf
.f_bsize
/1024)));
252 sprintf(S
,"%lu %lu",(long)(Buf
.f_blocks
*(Buf
.f_bsize
/1024)),
253 (long)(Buf
.f_bfree
*(Buf
.f_bsize
/1024)));
256 sprintf(S
,"-%u",Version
);
259 sprintf(S
,"-%u.debug",Version
);
261 Res
= Hash
.Result().Value() + S
;
266 // FindMountPointForDevice - Find mountpoint for the given device /*{{{*/
267 string
FindMountPointForDevice(const char *devnode
)
273 // this is the order that mount uses as well
274 const char *mount
[] = { "/etc/mtab",
278 for (i
=0; mount
[i
] != NULL
; i
++) {
279 if (FileExists(mount
[i
])) {
280 FILE *f
=fopen(mount
[i
], "r");
281 while ( fgets(buf
, sizeof(buf
), f
) != NULL
) {
282 if (strncmp(buf
, devnode
, strlen(devnode
)) == 0) {
283 if(TokSplitString(' ', buf
, out
, 10))
286 // unescape the \0XXX chars in the path
287 string mount_point
= out
[1];
288 return DeEscapeString(mount_point
);