]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/cdromutl.cc
* merged from the apt--install-recommends branch
[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 /*{{{*/
13#ifdef __GNUG__
14#pragma implementation "apt-pkg/cdromutl.h"
15#endif
16#include <apt-pkg/cdromutl.h>
17#include <apt-pkg/error.h>
18#include <apt-pkg/md5.h>
19#include <apt-pkg/fileutl.h>
6c907975 20#include <apt-pkg/configuration.h>
d669751b 21
b2e465d6
AL
22#include <apti18n.h>
23
d669751b
AL
24#include <sys/wait.h>
25#include <sys/errno.h>
101030ab 26#include <sys/statvfs.h>
d669751b
AL
27#include <dirent.h>
28#include <fcntl.h>
4df0b629 29#include <sys/stat.h>
d669751b
AL
30#include <unistd.h>
31#include <stdio.h>
32 /*}}}*/
33
6c907975 34// IsMounted - Returns true if the mount point is mounted /*{{{*/
d669751b 35// ---------------------------------------------------------------------
6c907975
AL
36/* This is a simple algorithm that should always work, we stat the mount point
37 and the '..' file in the mount point and see if they are on the same device.
38 By definition if they are the same then it is not mounted. This should
39 account for symlinked mount points as well. */
40bool IsMounted(string &Path)
d669751b 41{
4df0b629
AL
42 if (Path.empty() == true)
43 return false;
44
45 // Need that trailing slash for directories
46 if (Path[Path.length() - 1] != '/')
47 Path += '/';
48
49 /* First we check if the path is actualy mounted, we do this by
50 stating the path and the previous directory (carefull of links!)
51 and comparing their device fields. */
52 struct stat Buf,Buf2;
53 if (stat(Path.c_str(),&Buf) != 0 ||
54 stat((Path + "../").c_str(),&Buf2) != 0)
b2e465d6 55 return _error->Errno("stat",_("Unable to stat the mount point %s"),Path.c_str());
4df0b629
AL
56
57 if (Buf.st_dev == Buf2.st_dev)
6c907975
AL
58 return false;
59 return true;
60}
61 /*}}}*/
62// UnmountCdrom - Unmount a cdrom /*{{{*/
63// ---------------------------------------------------------------------
64/* Forking umount works much better than the umount syscall which can
65 leave /etc/mtab inconsitant. We drop all messages this produces. */
66bool UnmountCdrom(string Path)
67{
68 if (IsMounted(Path) == false)
4df0b629
AL
69 return true;
70
54676e1a 71 int Child = ExecFork();
d669751b
AL
72
73 // The child
74 if (Child == 0)
75 {
76 // Make all the fds /dev/null
d669751b
AL
77 for (int I = 0; I != 3; I++)
78 dup2(open("/dev/null",O_RDWR),I);
79
6c907975
AL
80 if (_config->Exists("Acquire::cdrom::"+Path+"::UMount") == true)
81 {
82 if (system(_config->Find("Acquire::cdrom::"+Path+"::UMount").c_str()) != 0)
83 _exit(100);
84 _exit(0);
85 }
86 else
87 {
88 const char *Args[10];
89 Args[0] = "umount";
90 Args[1] = Path.c_str();
91 Args[2] = 0;
92 execvp(Args[0],(char **)Args);
93 _exit(100);
94 }
d669751b
AL
95 }
96
97 // Wait for mount
b2e465d6 98 return ExecWait(Child,"umount",true);
d669751b
AL
99}
100 /*}}}*/
101// MountCdrom - Mount a cdrom /*{{{*/
102// ---------------------------------------------------------------------
103/* We fork mount and drop all messages */
104bool MountCdrom(string Path)
105{
6c907975
AL
106 if (IsMounted(Path) == true)
107 return true;
108
54676e1a 109 int Child = ExecFork();
d669751b
AL
110
111 // The child
112 if (Child == 0)
113 {
114 // Make all the fds /dev/null
d669751b
AL
115 for (int I = 0; I != 3; I++)
116 dup2(open("/dev/null",O_RDWR),I);
117
6c907975
AL
118 if (_config->Exists("Acquire::cdrom::"+Path+"::Mount") == true)
119 {
120 if (system(_config->Find("Acquire::cdrom::"+Path+"::Mount").c_str()) != 0)
121 _exit(100);
122 _exit(0);
123 }
124 else
125 {
126 const char *Args[10];
127 Args[0] = "mount";
128 Args[1] = Path.c_str();
129 Args[2] = 0;
130 execvp(Args[0],(char **)Args);
131 _exit(100);
132 }
d669751b
AL
133 }
134
135 // Wait for mount
ddc1d8d0 136 return ExecWait(Child,"mount",true);
d669751b
AL
137}
138 /*}}}*/
139// IdentCdrom - Generate a unique string for this CD /*{{{*/
140// ---------------------------------------------------------------------
141/* We convert everything we hash into a string, this prevents byte size/order
142 from effecting the outcome. */
34fc0421 143bool IdentCdrom(string CD,string &Res,unsigned int Version)
d669751b
AL
144{
145 MD5Summation Hash;
146
147 string StartDir = SafeGetCWD();
148 if (chdir(CD.c_str()) != 0)
b2e465d6 149 return _error->Errno("chdir",_("Unable to change to %s"),CD.c_str());
d669751b
AL
150
151 DIR *D = opendir(".");
152 if (D == 0)
b2e465d6 153 return _error->Errno("opendir",_("Unable to read %s"),CD.c_str());
d669751b 154
4df0b629
AL
155 /* Run over the directory, we assume that the reader order will never
156 change as the media is read-only. In theory if the kernel did
157 some sort of wacked caching this might not be true.. */
d669751b
AL
158 char S[300];
159 for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
160 {
161 // Skip some files..
162 if (strcmp(Dir->d_name,".") == 0 ||
163 strcmp(Dir->d_name,"..") == 0)
164 continue;
34fc0421
AL
165
166 if (Version <= 1)
167 {
0f297e46 168 sprintf(S,"%lu",(unsigned long)Dir->d_ino);
34fc0421
AL
169 }
170 else
171 {
172 struct stat Buf;
173 if (stat(Dir->d_name,&Buf) != 0)
174 continue;
1ae93c94 175 sprintf(S,"%lu",(unsigned long)Buf.st_mtime);
34fc0421
AL
176 }
177
d669751b
AL
178 Hash.Add(S);
179 Hash.Add(Dir->d_name);
180 };
181
182 chdir(StartDir.c_str());
183 closedir(D);
184
185 // Some stats from the fsys
fbdccabb
AL
186 if (_config->FindB("Debug::identcdrom",false) == false)
187 {
101030ab
AL
188 struct statvfs Buf;
189 if (statvfs(CD.c_str(),&Buf) != 0)
b2e465d6 190 return _error->Errno("statfs",_("Failed to stat the cdrom"));
fbdccabb
AL
191
192 // We use a kilobyte block size to advoid overflow
193 sprintf(S,"%lu %lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)),
194 (long)(Buf.f_bfree*(Buf.f_bsize/1024)));
195 Hash.Add(S);
196 sprintf(S,"-%u",Version);
197 }
198 else
199 sprintf(S,"-%u.debug",Version);
d669751b 200
34fc0421 201 Res = Hash.Result().Value() + S;
d669751b
AL
202 return true;
203}
204 /*}}}*/