~ubuntu-branches/ubuntu/karmic/kleansweep/karmic

« back to all changes in this revision

Viewing changes to src/sweepscanner.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Mercatante
  • Date: 2006-01-20 11:26:41 UTC
  • Revision ID: james.westby@ubuntu.com-20060120112641-xd1rmv568k0vvz3u
Tags: upstream-0.2.5
ImportĀ upstreamĀ versionĀ 0.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is a part of KleanSweep.
 
3
 *
 
4
 * Copyright (C) 2005 Pawel Stolowski <pawel.stolowski@wp.pl>
 
5
 *
 
6
 * KleanSweep is free software; you can redestribute it and/or modify it
 
7
 * under terms of GNU General Public License by Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY. See GPL for more details.
 
11
 */
 
12
 
 
13
#include "sweepscanner.h"
 
14
#include "sweepfileinfo.h"
 
15
#include "kleansweepcfg.h"
 
16
#include <kprocess.h>
 
17
#include <kstandarddirs.h>
 
18
#include <qtextstream.h>
 
19
#include <cstdlib>
 
20
#include <cctype>
 
21
 
 
22
#ifdef DEBUG
 
23
#include <qvaluelist.h>
 
24
#include <iostream>
 
25
#endif
 
26
 
 
27
#define MAX_LINE_LEN 1024
 
28
 
 
29
SweepScanner::SweepScanner(): QObject(), lineptr(0), writable(false)
 
30
{
 
31
        line = new char [MAX_LINE_LEN];
 
32
        for (int i=0; i<NONE; i++)
 
33
                ftypes[i] = false;
 
34
        files.setAutoDelete(true);
 
35
        
 
36
        proc = new KProcess(this);
 
37
        connect(proc, SIGNAL(receivedStdout(KProcess *, char *, int)), this, SLOT(onProcessData(KProcess *, char *, int)));
 
38
        connect(proc, SIGNAL(processExited(KProcess *)), this, SLOT(helperExited(KProcess *)));
 
39
}
 
40
 
 
41
SweepScanner::~SweepScanner()
 
42
{
 
43
        stop();
 
44
        delete line;
 
45
}
 
46
 
 
47
void SweepScanner::enableFileType(FileType f, bool enable)
 
48
{
 
49
        if (ftypes[f] != enable)
 
50
                ftypes[f] = enable;
 
51
}
 
52
 
 
53
void SweepScanner::setOnlyWritable(bool f)
 
54
{
 
55
        if (writable != f)
 
56
                writable = f;
 
57
}
 
58
 
 
59
bool SweepScanner::getOnlyWritable() const
 
60
{
 
61
        return writable;
 
62
}
 
63
 
 
64
bool SweepScanner::isEnabled(FileType f)
 
65
{
 
66
        return ftypes[f];
 
67
}
 
68
 
 
69
void SweepScanner::clear()
 
70
{
 
71
        files.clear();
 
72
        filemap.clear();
 
73
}
 
74
 
 
75
bool SweepScanner::start(const QString &path)
 
76
{
 
77
        if (proc->isRunning())
 
78
                return false;
 
79
 
 
80
        clear();
 
81
        lineptr = totalitems = totalsize = 0;
 
82
 
 
83
        KleanSweepConfig *cfg = &KleanSweepConfig::instance();
 
84
        const QString bl = ::locate("data", "kleansweep/kleansweep-blacklist");
 
85
        const QString ru = ::locate("data", "kleansweep/kleansweep-rules");
 
86
 
 
87
        proc->clearArguments();
 
88
        *proc << "kleansweep-helper";
 
89
        if (!bl.isEmpty())
 
90
                *proc << "--blacklist" << bl; 
 
91
        if (!ru.isEmpty())
 
92
                *proc << "--scoring" << ru;
 
93
        if (cfg->showProgress())
 
94
                *proc << "--progress";
 
95
        if (writable)
 
96
                *proc << "--writable";
 
97
        if (isEnabled(EMPTY_FILE))      *proc << "-z";
 
98
        if (isEnabled(BACKUP_FILE))     *proc << "-b";
 
99
        if (isEnabled(EMPTY_DIR))       *proc << "-y";
 
100
        if (isEnabled(BROKEN_SYMLINK))  *proc << "-s";
 
101
        //if (isEnabled(OLD_FILE))        *proc << "--unused" << QString::number(cfg->oldFilesAge());
 
102
        if (isEnabled(DUPLICATED_FILE)) *proc << "-d";
 
103
        if (isEnabled(ORPHAN_FILE))
 
104
        {
 
105
                const DistroPkg pkg = cfg->distroPackageManager();
 
106
                if (pkg == RPM)
 
107
                        *proc << "--rpm";
 
108
                else if (pkg == DPKG)
 
109
                        *proc << "--deb";
 
110
        }
 
111
        if (isEnabled(DEAD_MENUENTRY))  *proc << "-m";
 
112
        if (isEnabled(DEAD_THUMBNAIL))  *proc << "-t";
 
113
        if (isEnabled(BROKEN_EXEC))     *proc << "-x";
 
114
        if (isEnabled(UNUSED_LOCALE))   *proc << "-l";
 
115
 
 
116
        QStringList paths = cfg->globalExcludePaths();
 
117
        for (QStringList::iterator it = paths.begin(); it != paths.end(); ++it)
 
118
                *proc << "--exclude" << *it;
 
119
 
 
120
        if (isEnabled(ORPHAN_FILE))
 
121
        {
 
122
                paths = cfg->orphansExcludePaths();
 
123
                for (QStringList::iterator it = paths.begin(); it != paths.end(); ++it)
 
124
                        *proc << "--orphans-exclude" << *it;
 
125
                paths = cfg->orphansIncludePaths();
 
126
                for (QStringList::iterator it = paths.begin(); it != paths.end(); ++it)
 
127
                        *proc << "--orphans-include" << *it;
 
128
        }
 
129
        
 
130
        *proc << path;
 
131
        proc->setPriority(10);
 
132
 
 
133
        #ifdef  DEBUG
 
134
        //
 
135
        // print helper arguments
 
136
        const QValueList<QCString> alist = proc->args();
 
137
        for (QValueList<QCString>::const_iterator it = alist.begin(); it != alist.end(); it++)
 
138
                std::cerr << *it << " ";
 
139
        std::cerr << std::endl;
 
140
        #endif
 
141
        
 
142
        if (!proc->start(KProcess::NotifyOnExit, KProcess::Stdout))
 
143
                return false;
 
144
        last_path = path;
 
145
        return true;
 
146
}
 
147
 
 
148
bool SweepScanner::isRunning()
 
149
{
 
150
        return proc->isRunning();
 
151
}
 
152
 
 
153
bool SweepScanner::stop()
 
154
{
 
155
        if (isRunning())
 
156
                proc->kill(SIGTERM);
 
157
        return true;
 
158
}
 
159
 
 
160
void SweepScanner::onProcessData(KProcess *proc, char *buf, int len)
 
161
{
 
162
        for (int i=0; i<len; i++)
 
163
        {
 
164
                if (buf[i] == '\n')
 
165
                {
 
166
                        line[lineptr] = 0;
 
167
                        lineptr = 0;
 
168
                        extractFileInfo();
 
169
                }
 
170
                else
 
171
                {
 
172
                        line[lineptr++] = buf[i];
 
173
                        if (lineptr == MAX_LINE_LEN-1)
 
174
                        {
 
175
                                ;
 
176
                        }
 
177
                }
 
178
        }
 
179
}
 
180
 
 
181
void SweepScanner::extractFileInfo()
 
182
{
 
183
        int pos = 0;
 
184
        char score = 0;
 
185
        long id = -1;
 
186
        SweepFileInfo *f = NULL;
 
187
        SweepFileInfo *dupparent = NULL;
 
188
 
 
189
        #ifdef DEBUG
 
190
        std::cerr << line << std::endl;
 
191
        #endif
 
192
 
 
193
        if (line[0] == '@')
 
194
        {
 
195
                emit currentPath(line + 2);
 
196
                return;
 
197
        }
 
198
        if (isdigit(line[pos]))
 
199
        {
 
200
                score = line[pos++] - '0';
 
201
                if (isdigit(line[pos]))
 
202
                {
 
203
                        id = atol(line + pos);
 
204
                        while (isdigit(line[pos])) //skip digits
 
205
                                ++pos;
 
206
                }
 
207
        }
 
208
 
 
209
        //
 
210
        // find file name
 
211
        int namepos = pos;
 
212
        while (line[namepos])
 
213
        {
 
214
                if (line[namepos] == ':')
 
215
                {
 
216
                        line[namepos++] = 0;
 
217
                        break;
 
218
                }
 
219
                else if (line[namepos] == '\\')
 
220
                {
 
221
                        namepos += 2;
 
222
                }
 
223
                else
 
224
                        ++namepos;
 
225
        }
 
226
        
 
227
        KURL path;
 
228
        path.setPath(line + namepos);
 
229
 
 
230
        if (filemap.contains(id))
 
231
        {
 
232
                if (filemap[id]->url().path() == (line + namepos))
 
233
                {
 
234
                        f = filemap[id];
 
235
                }
 
236
                else
 
237
                {
 
238
                        dupparent = filemap[id];
 
239
                        f = new SweepFileInfo(path, score);
 
240
                        files.append(f);
 
241
                        totalsize += f->size();
 
242
                        emit updateTotals(++totalitems, totalsize);
 
243
                }
 
244
        }
 
245
        else
 
246
        {
 
247
                f = new SweepFileInfo(path, score);
 
248
                filemap.insert(id, f);
 
249
                files.append(f);
 
250
                totalsize += f->size();
 
251
                emit updateTotals(++totalitems, totalsize);
 
252
        }
 
253
        
 
254
        for (pos=0; line[pos];)
 
255
        { 
 
256
                FileType ft;
 
257
                switch (line[pos])
 
258
                {
 
259
                        case 'y': ft = EMPTY_DIR; break;
 
260
                        case 'z': ft = EMPTY_FILE; break;
 
261
                        case 'l': ft = UNUSED_LOCALE; break;
 
262
                        case 'b': ft = BACKUP_FILE; break;
 
263
                        case 'm': ft = DEAD_MENUENTRY; break;
 
264
                        case 'd': ft = DUPLICATED_FILE; break;
 
265
                        case 's': ft = BROKEN_SYMLINK; break;
 
266
                        case 't': ft = DEAD_THUMBNAIL; break;
 
267
                        case 'x': ft = BROKEN_EXEC; break;
 
268
                        //case 'U': ft = OLD_FILE; break;
 
269
                        case 'O': ft = ORPHAN_FILE; break;
 
270
                        default: ft = NONE; break;
 
271
                }
 
272
                ++pos;
 
273
                if (ft == DUPLICATED_FILE)
 
274
                {
 
275
                        if (dupparent)
 
276
                        {
 
277
                                emit newFileEntry(ft, f, dupparent);
 
278
                        }
 
279
                        else
 
280
                        {
 
281
                                emit newFileEntry(ft, f);
 
282
                        }
 
283
                        break; //?????
 
284
                }
 
285
                if (ft == DEAD_MENUENTRY || ft == DEAD_THUMBNAIL || ft == BROKEN_SYMLINK || ft == BROKEN_EXEC)
 
286
                {
 
287
                        int targetpos = pos;
 
288
                        //
 
289
                        // parse target
 
290
                        // - puts \0 in place of closing ','
 
291
                        // - removes escape backslash-characters (replaces original string)
 
292
                        for (int dst = pos; line[pos]; dst++)
 
293
                        {
 
294
                                if (line[pos] == ',')
 
295
                                {
 
296
                                        line[dst] = 0;
 
297
                                        ++pos;
 
298
                                        break;
 
299
                                }
 
300
                                if (line[pos] == '\\') //backslash found - take next character 'as is'
 
301
                                        line[dst] = line[++pos];
 
302
                                else
 
303
                                        line[dst] = line[pos];
 
304
                                ++pos;
 
305
                        }
 
306
                        f->setTarget(line + targetpos);
 
307
                }
 
308
                if (ft != NONE && ftypes[ft])
 
309
                        emit newFileEntry(ft, f);
 
310
        }
 
311
}
 
312
 
 
313
void SweepScanner::helperExited(KProcess *proc)
 
314
{
 
315
        filemap.clear(); //no longer needed
 
316
        emit finished(true);
 
317
}
 
318
 
 
319
QPtrList<SweepFileInfo> SweepScanner::getFilesForRemoval()
 
320
{
 
321
        QPtrList<SweepFileInfo> remfiles;
 
322
        remfiles.setAutoDelete(false);
 
323
        for (SweepFileInfo *finfo = files.first(); finfo; finfo = files.next())
 
324
                if (finfo->isMarkedForRemoval() && finfo->getScore()>0) //score can't be 0 if file is marked for removal -- sanity check...
 
325
                        remfiles.append(finfo);
 
326
        return remfiles;
 
327
}
 
328
 
 
329
QString SweepScanner::lastScanPath() const
 
330
{
 
331
        return last_path;
 
332
}
 
333
 
 
334
void SweepScanner::writeLog(QTextStream &str)
 
335
{
 
336
        for (SweepFileInfo *finfo = files.first(); finfo; finfo = files.next())
 
337
                str << (finfo->isMarkedForRemoval() ? "[+] " : "[-] ") << finfo->getScore() << ' ' << QString(finfo->url().path()) << "\n";
 
338
}
 
339
 
 
340
#include "sweepscanner.moc"