Fixed initialization problem
[ntk/apt.git] / apt-pkg / contrib / cdromutl.cc
CommitLineData
d669751b
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
4df0b629 3// $Id: cdromutl.cc,v 1.2 1999/03/28 01:37:26 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>
20
21#include <sys/wait.h>
22#include <sys/errno.h>
23#include <sys/vfs.h>
24#include <dirent.h>
25#include <fcntl.h>
4df0b629 26#include <sys/stat.h>
d669751b
AL
27#include <unistd.h>
28#include <stdio.h>
29 /*}}}*/
30
31// UnmountCdrom - Unmount a cdrom /*{{{*/
32// ---------------------------------------------------------------------
33/* Forking umount works much better than the umount syscall which can
34 leave /etc/mtab inconsitant. We drop all messages this produces. */
35bool UnmountCdrom(string Path)
36{
4df0b629
AL
37 if (Path.empty() == true)
38 return false;
39
40 // Need that trailing slash for directories
41 if (Path[Path.length() - 1] != '/')
42 Path += '/';
43
44 /* First we check if the path is actualy mounted, we do this by
45 stating the path and the previous directory (carefull of links!)
46 and comparing their device fields. */
47 struct stat Buf,Buf2;
48 if (stat(Path.c_str(),&Buf) != 0 ||
49 stat((Path + "../").c_str(),&Buf2) != 0)
50 return _error->Errno("stat","Unable to stat the mount point %s",Path.c_str());
51
52 if (Buf.st_dev == Buf2.st_dev)
53 return true;
54
d669751b
AL
55 int Child = fork();
56 if (Child < -1)
57 return _error->Errno("fork","Failed to fork");
58
59 // The child
60 if (Child == 0)
61 {
62 // Make all the fds /dev/null
63 for (int I = 0; I != 10; I++)
64 close(I);
65 for (int I = 0; I != 3; I++)
66 dup2(open("/dev/null",O_RDWR),I);
67
68 const char *Args[10];
69 Args[0] = "umount";
70 Args[1] = Path.c_str();
71 Args[2] = 0;
72 execvp(Args[0],(char **)Args);
73 exit(100);
74 }
75
76 // Wait for mount
77 int Status = 0;
78 while (waitpid(Child,&Status,0) != Child)
79 {
80 if (errno == EINTR)
81 continue;
82 return _error->Errno("waitpid","Couldn't wait for subprocess");
83 }
84
85 // Check for an error code.
86 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
87 return false;
88 return true;
89}
90 /*}}}*/
91// MountCdrom - Mount a cdrom /*{{{*/
92// ---------------------------------------------------------------------
93/* We fork mount and drop all messages */
94bool MountCdrom(string Path)
95{
96 int Child = fork();
97 if (Child < -1)
98 return _error->Errno("fork","Failed to fork");
99
100 // The child
101 if (Child == 0)
102 {
103 // Make all the fds /dev/null
104 for (int I = 0; I != 10; I++)
105 close(I);
106 for (int I = 0; I != 3; I++)
107 dup2(open("/dev/null",O_RDWR),I);
108
109 const char *Args[10];
110 Args[0] = "mount";
111 Args[1] = Path.c_str();
112 Args[2] = 0;
113 execvp(Args[0],(char **)Args);
114 exit(100);
115 }
116
117 // Wait for mount
118 int Status = 0;
119 while (waitpid(Child,&Status,0) != Child)
120 {
121 if (errno == EINTR)
122 continue;
123 return _error->Errno("waitpid","Couldn't wait for subprocess");
124 }
125
126 // Check for an error code.
127 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
128 return false;
129 return true;
130}
131 /*}}}*/
132// IdentCdrom - Generate a unique string for this CD /*{{{*/
133// ---------------------------------------------------------------------
134/* We convert everything we hash into a string, this prevents byte size/order
135 from effecting the outcome. */
136bool IdentCdrom(string CD,string &Res)
137{
138 MD5Summation Hash;
139
140 string StartDir = SafeGetCWD();
141 if (chdir(CD.c_str()) != 0)
142 return _error->Errno("chdir","Unable to change to %s",CD.c_str());
143
144 DIR *D = opendir(".");
145 if (D == 0)
146 return _error->Errno("opendir","Unable to read %s",CD.c_str());
147
4df0b629
AL
148 /* Run over the directory, we assume that the reader order will never
149 change as the media is read-only. In theory if the kernel did
150 some sort of wacked caching this might not be true.. */
d669751b
AL
151 char S[300];
152 for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
153 {
154 // Skip some files..
155 if (strcmp(Dir->d_name,".") == 0 ||
156 strcmp(Dir->d_name,"..") == 0)
157 continue;
158
159 sprintf(S,"%lu",Dir->d_ino);
160 Hash.Add(S);
161 Hash.Add(Dir->d_name);
162 };
163
164 chdir(StartDir.c_str());
165 closedir(D);
166
167 // Some stats from the fsys
168 struct statfs Buf;
169 if (statfs(CD.c_str(),&Buf) != 0)
170 return _error->Errno("statfs","Failed to stat the cdrom");
4df0b629
AL
171
172 // We use a kilobyte block size to advoid overflow
173 sprintf(S,"%u %u",Buf.f_blocks*(Buf.f_bsize/1024),
174 Buf.f_bfree*(Buf.f_bsize/1024));
d669751b
AL
175 Hash.Add(S);
176
177 Res = Hash.Result().Value();
178 return true;
179}
180 /*}}}*/