~ubuntu-branches/ubuntu/quantal/kde4libs/quantal

« back to all changes in this revision

Viewing changes to .pc/kfreebsd_support.diff/kioslave/file/file_unix.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer, Philip Muškovac, Jonathan Thomas, Felix Geyer
  • Date: 2011-05-29 17:19:55 UTC
  • mfrom: (1.14.5 upstream) (0.1.19 sid)
  • Revision ID: package-import@ubuntu.com-20110529171955-nodep1593tuwyu6k
Tags: 4:4.6.3-1ubuntu1
[ Philip Muškovac]
* Drop kubuntu_83_fix_solid_network_status.diff
* Update Vcs links as the branch is owned by kubuntu-packagers now

[ Jonathan Thomas ]
* Drop kubuntu_06_user_disk_mounting. We no longer compile the hal
  backend, so this patch is useless.

[ Felix Geyer ]
* Merge from Debian unstable, remaining changes:
  - no build-dep on libaspell-dev
  - no build-dep on libfam-dev
  - kdelibs5-data: don't install kspell_aspell.desktop and
    usr/lib/kde4/kspell_aspell.so
  - kdelibs5-dev: don't install preparetips
  - Pass -DKDESU_USE_SUDO_DEFAULT=true to configure
  - dh_fixperms: exclude /usr/lib/kde4/libexec/fileshareset
  - set export KUBUNTU_DESKTOP_POT=kdelibs
  - don't apply use_dejavu_as_default_font.diff
  - don't apply kconf_update_migrate_from_kde3_icon_theme.diff
    - kdelibs5-data.install: drop usr/share/kde4/apps/kconf_update/kdeui.upd
  - don't build depend on libglu1-mesa-dev, not needed due to
    kubuntu_no_direct_gl_usage.diff
  - Add kdelibs5-data.links: link from /usr/share/doc/kde4 to kde for
    backwards compatible with old docs location
  - Keep the kdelibs5 transitional package
  - kdelibs5-dev.install: install ksambasharedata.h
  - kdelibs5-plugins: recommend ttf-dejavu-core instead of ttf-dejavu to save
    CD space.
* Add Breaks in addition to Replaces for moving files between packages.
* Drop no longer needed Breaks and Replaces.
* Completely drop kubuntu_51_launchpad_integration.diff and
  kubuntu_68_remove_applet_confirmation.diff.
  + Also drop the launchpad and kubuntu icons.
* Remove sequence numbers from kubuntu patches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (C) 2000-2002 Stephan Kulow <coolo@kde.org>
 
3
   Copyright (C) 2000-2002 David Faure <faure@kde.org>
 
4
   Copyright (C) 2000-2002 Waldo Bastian <bastian@kde.org>
 
5
   Copyright (C) 2006 Allan Sandfeld Jensen <sandfeld@kde.org>
 
6
   Copyright (C) 2007 Thiago Macieira <thiago@kde.org>
 
7
   Copyright (C) 2007 Christian Ehrlicher <ch.ehrlicher@gmx.de>
 
8
 
 
9
   This library is free software; you can redistribute it and/or
 
10
   modify it under the terms of the GNU Library General Public
 
11
   License (LGPL) as published by the Free Software Foundation;
 
12
   either version 2 of the License, or (at your option) any later
 
13
   version.
 
14
 
 
15
   This library is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
   Library General Public License for more details.
 
19
 
 
20
   You should have received a copy of the GNU Library General Public License
 
21
   along with this library; see the file COPYING.LIB.  If not, write to
 
22
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
23
   Boston, MA 02110-1301, USA.
 
24
*/
 
25
 
 
26
#define QT_NO_CAST_FROM_ASCII
 
27
 
 
28
#include "file.h"
 
29
 
 
30
#include <config.h>
 
31
 
 
32
#include <QtCore/QFile>
 
33
 
 
34
#include <kde_file.h>
 
35
#include <kdebug.h>
 
36
#include <kconfiggroup.h>
 
37
#include <kmountpoint.h>
 
38
 
 
39
#include <dirent.h>
 
40
#include <errno.h>
 
41
#include <fcntl.h>
 
42
#include <grp.h>
 
43
#include <utime.h>
 
44
#include <pwd.h>
 
45
#include <stdlib.h>
 
46
 
 
47
#if defined(HAVE_LIMITS_H)
 
48
#include <limits.h>  // PATH_MAX
 
49
#endif
 
50
 
 
51
//sendfile has different semantics in different platforms
 
52
#if defined HAVE_SENDFILE && defined Q_OS_LINUX
 
53
#define USE_SENDFILE 1
 
54
#endif
 
55
 
 
56
#ifdef USE_SENDFILE
 
57
#include <sys/sendfile.h>
 
58
#endif
 
59
 
 
60
namespace KDEPrivate
 
61
{
 
62
 
 
63
struct CharArrayDeleter
 
64
{
 
65
    CharArrayDeleter(char *b) : buf(b) {}
 
66
    ~CharArrayDeleter() { free(buf); }
 
67
    char *buf;
 
68
};
 
69
 
 
70
}
 
71
 
 
72
using namespace KIO;
 
73
 
 
74
#define MAX_IPC_SIZE (1024*32)
 
75
 
 
76
static bool
 
77
same_inode(const KDE_struct_stat &src, const KDE_struct_stat &dest)
 
78
{
 
79
   if (src.st_ino == dest.st_ino &&
 
80
       src.st_dev == dest.st_dev)
 
81
     return true;
 
82
 
 
83
   return false;
 
84
}
 
85
 
 
86
extern int write_all(int fd, const char *buf, size_t len);
 
87
 
 
88
void FileProtocol::copy( const KUrl &srcUrl, const KUrl &destUrl,
 
89
                         int _mode, JobFlags _flags )
 
90
{
 
91
    kDebug(7101) << "copy(): " << srcUrl << " -> " << destUrl << ", mode=" << _mode;
 
92
 
 
93
    const QString src = srcUrl.toLocalFile();
 
94
    const QString dest = destUrl.toLocalFile();
 
95
    QByteArray _src( QFile::encodeName(src));
 
96
    QByteArray _dest( QFile::encodeName(dest));
 
97
    KDE_struct_stat buff_src;
 
98
#ifdef HAVE_POSIX_ACL
 
99
    acl_t acl;
 
100
#endif
 
101
 
 
102
    if ( KDE_stat( _src.data(), &buff_src ) == -1 ) {
 
103
        if ( errno == EACCES )
 
104
           error(KIO::ERR_ACCESS_DENIED, src);
 
105
        else
 
106
           error(KIO::ERR_DOES_NOT_EXIST, src);
 
107
        return;
 
108
    }
 
109
 
 
110
    if ( S_ISDIR( buff_src.st_mode ) ) {
 
111
        error(KIO::ERR_IS_DIRECTORY, src);
 
112
        return;
 
113
    }
 
114
    if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) {
 
115
        error(KIO::ERR_CANNOT_OPEN_FOR_READING, src);
 
116
        return;
 
117
    }
 
118
 
 
119
    KDE_struct_stat buff_dest;
 
120
    bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
 
121
    if ( dest_exists )
 
122
    {
 
123
        if (S_ISDIR(buff_dest.st_mode))
 
124
        {
 
125
           error(KIO::ERR_DIR_ALREADY_EXIST, dest);
 
126
           return;
 
127
        }
 
128
 
 
129
        if ( same_inode( buff_dest, buff_src) )
 
130
        {
 
131
            error(KIO::ERR_IDENTICAL_FILES, dest);
 
132
            return;
 
133
        }
 
134
 
 
135
        if (!(_flags & KIO::Overwrite))
 
136
        {
 
137
           error(KIO::ERR_FILE_ALREADY_EXIST, dest);
 
138
           return;
 
139
        }
 
140
 
 
141
        // If the destination is a symlink and overwrite is TRUE,
 
142
        // remove the symlink first to prevent the scenario where
 
143
        // the symlink actually points to current source!
 
144
        if ((_flags & KIO::Overwrite) && S_ISLNK(buff_dest.st_mode))
 
145
        {
 
146
            //kDebug(7101) << "copy(): LINK DESTINATION";
 
147
            remove( _dest.data() );
 
148
        }
 
149
    }
 
150
 
 
151
    int src_fd = KDE_open( _src.data(), O_RDONLY);
 
152
    if ( src_fd < 0 ) {
 
153
        error(KIO::ERR_CANNOT_OPEN_FOR_READING, src);
 
154
        return;
 
155
    }
 
156
 
 
157
#ifdef HAVE_FADVISE
 
158
    posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL);
 
159
#endif
 
160
    // WABA: Make sure that we keep writing permissions ourselves,
 
161
    // otherwise we can be in for a surprise on NFS.
 
162
    mode_t initialMode;
 
163
    if (_mode != -1)
 
164
       initialMode = _mode | S_IWUSR;
 
165
    else
 
166
       initialMode = 0666;
 
167
 
 
168
    int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
 
169
    if ( dest_fd < 0 ) {
 
170
        kDebug(7101) << "###### COULD NOT WRITE " << dest;
 
171
        if ( errno == EACCES ) {
 
172
            error(KIO::ERR_WRITE_ACCESS_DENIED, dest);
 
173
        } else {
 
174
            error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest);
 
175
        }
 
176
        ::close(src_fd);
 
177
        return;
 
178
    }
 
179
 
 
180
#ifdef HAVE_FADVISE
 
181
    posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL);
 
182
#endif
 
183
 
 
184
#ifdef HAVE_POSIX_ACL
 
185
    acl = acl_get_fd(src_fd);
 
186
    if ( acl && !isExtendedACL( acl ) ) {
 
187
        kDebug(7101) << _dest.data() << " doesn't have extended ACL";
 
188
        acl_free( acl );
 
189
        acl = NULL;
 
190
    }
 
191
#endif
 
192
    totalSize( buff_src.st_size );
 
193
 
 
194
    KIO::filesize_t processed_size = 0;
 
195
    char buffer[ MAX_IPC_SIZE ];
 
196
    int n;
 
197
#ifdef USE_SENDFILE
 
198
    bool use_sendfile=buff_src.st_size < 0x7FFFFFFF;
 
199
#endif
 
200
    while( 1 )
 
201
    {
 
202
#ifdef USE_SENDFILE
 
203
       if (use_sendfile) {
 
204
            off_t sf = processed_size;
 
205
            n = KDE_sendfile( dest_fd, src_fd, &sf, MAX_IPC_SIZE );
 
206
            processed_size = sf;
 
207
            if ( n == -1 && ( errno == EINVAL || errno == ENOSYS ) ) { //not all filesystems support sendfile()
 
208
                kDebug(7101) << "sendfile() not supported, falling back ";
 
209
                use_sendfile = false;
 
210
            }
 
211
       }
 
212
       if (!use_sendfile)
 
213
#endif
 
214
        n = ::read( src_fd, buffer, MAX_IPC_SIZE );
 
215
 
 
216
       if (n == -1)
 
217
       {
 
218
          if (errno == EINTR)
 
219
              continue;
 
220
#ifdef USE_SENDFILE
 
221
          if ( use_sendfile ) {
 
222
            kDebug(7101) << "sendfile() error:" << strerror(errno);
 
223
            if ( errno == ENOSPC ) // disk full
 
224
            {
 
225
                error(KIO::ERR_DISK_FULL, dest);
 
226
                remove( _dest.data() );
 
227
            }
 
228
            else {
 
229
                error(KIO::ERR_SLAVE_DEFINED,
 
230
                      i18n("Cannot copy file from %1 to %2. (Errno: %3)",
 
231
                      src, dest, errno));
 
232
            }
 
233
          } else
 
234
#endif
 
235
          error(KIO::ERR_COULD_NOT_READ, src);
 
236
          ::close(src_fd);
 
237
          ::close(dest_fd);
 
238
#ifdef HAVE_POSIX_ACL
 
239
          if (acl) acl_free(acl);
 
240
#endif
 
241
          return;
 
242
       }
 
243
       if (n == 0)
 
244
          break; // Finished
 
245
#ifdef USE_SENDFILE
 
246
       if ( !use_sendfile ) {
 
247
#endif
 
248
         if (write_all( dest_fd, buffer, n))
 
249
         {
 
250
           ::close(src_fd);
 
251
           ::close(dest_fd);
 
252
 
 
253
           if ( errno == ENOSPC ) // disk full
 
254
           {
 
255
              error(KIO::ERR_DISK_FULL, dest);
 
256
              remove( _dest.data() );
 
257
           }
 
258
           else
 
259
           {
 
260
              kWarning(7101) << "Couldn't write[2]. Error:" << strerror(errno);
 
261
              error(KIO::ERR_COULD_NOT_WRITE, dest);
 
262
           }
 
263
#ifdef HAVE_POSIX_ACL
 
264
           if (acl) acl_free(acl);
 
265
#endif
 
266
           return;
 
267
         }
 
268
         processed_size += n;
 
269
#ifdef USE_SENDFILE
 
270
       }
 
271
#endif
 
272
       processedSize( processed_size );
 
273
    }
 
274
 
 
275
    ::close( src_fd );
 
276
 
 
277
    if (::close( dest_fd))
 
278
    {
 
279
        kWarning(7101) << "Error when closing file descriptor[2]:" << strerror(errno);
 
280
        error(KIO::ERR_COULD_NOT_WRITE, dest);
 
281
#ifdef HAVE_POSIX_ACL
 
282
        if (acl) acl_free(acl);
 
283
#endif
 
284
        return;
 
285
    }
 
286
 
 
287
    // set final permissions
 
288
    if ( _mode != -1 )
 
289
    {
 
290
        if ( (::chmod(_dest.data(), _mode) != 0)
 
291
#ifdef HAVE_POSIX_ACL
 
292
          || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0)
 
293
#endif
 
294
        )
 
295
       {
 
296
           KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest);
 
297
           // Eat the error if the filesystem apparently doesn't support chmod.
 
298
           if ( mp && mp->testFileSystemFlag( KMountPoint::SupportsChmod ) )
 
299
               warning(i18n("Could not change permissions for\n%1", dest));
 
300
       }
 
301
    }
 
302
#ifdef HAVE_POSIX_ACL
 
303
    if (acl) acl_free(acl);
 
304
#endif
 
305
 
 
306
    // copy access and modification time
 
307
    struct utimbuf ut;
 
308
    ut.actime = buff_src.st_atime;
 
309
    ut.modtime = buff_src.st_mtime;
 
310
    if ( ::utime( _dest.data(), &ut ) != 0 )
 
311
    {
 
312
        kWarning() << QString::fromLatin1("Couldn't preserve access and modification time for\n%1").arg(dest);
 
313
    }
 
314
 
 
315
    processedSize( buff_src.st_size );
 
316
    finished();
 
317
}
 
318
 
 
319
void FileProtocol::listDir( const KUrl& url)
 
320
{
 
321
    if (!url.isLocalFile()) {
 
322
        KUrl redir(url);
 
323
        redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
 
324
        redirection(redir);
 
325
        kDebug(7101) << "redirecting to " << redir.url();
 
326
        finished();
 
327
        return;
 
328
    }
 
329
    const QString path(url.toLocalFile());
 
330
    const QByteArray _path(QFile::encodeName(path));
 
331
    DIR* dp = opendir(_path.data());
 
332
    if ( dp == 0 ) {
 
333
        switch (errno) {
 
334
        case ENOENT:
 
335
            error(KIO::ERR_DOES_NOT_EXIST, path);
 
336
            return;
 
337
        case ENOTDIR:
 
338
            error(KIO::ERR_IS_FILE, path);
 
339
            break;
 
340
#ifdef ENOMEDIUM
 
341
        case ENOMEDIUM:
 
342
            error(ERR_SLAVE_DEFINED,
 
343
                  i18n("No media in device for %1", path));
 
344
            break;
 
345
#endif
 
346
        default:
 
347
            error(KIO::ERR_CANNOT_ENTER_DIRECTORY, path);
 
348
            break;
 
349
        }
 
350
        return;
 
351
    }
 
352
 
 
353
    const QString sDetails = metaData(QLatin1String("details"));
 
354
    const int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
 
355
    //kDebug(7101) << "========= LIST " << url << "details=" << details << " =========";
 
356
    UDSEntry entry;
 
357
 
 
358
#ifndef HAVE_DIRENT_D_TYPE
 
359
    KDE_struct_stat st;
 
360
#endif
 
361
    // Don't make this a QStringList. The locale file name we get here
 
362
    // should be passed intact to createUDSEntry to avoid problems with
 
363
    // files where QFile::encodeName(QFile::decodeName(a)) != a.
 
364
    QList<QByteArray> entryNames;
 
365
    KDE_struct_dirent *ep;
 
366
    if (details == 0) {
 
367
        // Fast path (for recursive deletion, mostly)
 
368
        // Simply emit the name and file type, nothing else.
 
369
        while ( ( ep = KDE_readdir( dp ) ) != 0 ) {
 
370
            entry.clear();
 
371
            entry.insert(KIO::UDSEntry::UDS_NAME, QFile::decodeName(ep->d_name));
 
372
#ifdef HAVE_DIRENT_D_TYPE
 
373
            entry.insert(KIO::UDSEntry::UDS_FILE_TYPE,
 
374
                         (ep->d_type & DT_DIR) ? S_IFDIR : S_IFREG );
 
375
            const bool isSymLink = (ep->d_type & DT_LNK);
 
376
#else
 
377
            // oops, no fast way, we need to stat (e.g. on Solaris)
 
378
            if (KDE_lstat(ep->d_name, &st) == -1) {
 
379
                continue; // how can stat fail?
 
380
            }
 
381
            entry.insert(KIO::UDSEntry::UDS_FILE_TYPE,
 
382
                          (S_ISDIR(st.st_mode)) ? S_IFDIR : S_IFREG );
 
383
            const bool isSymLink = S_ISLNK(st.st_mode);
 
384
#endif
 
385
            if (isSymLink) {
 
386
                // for symlinks obey the UDSEntry contract and provide UDS_LINK_DEST
 
387
                // even if we don't know the link dest (and DeleteJob doesn't care...)
 
388
                entry.insert(KIO::UDSEntry::UDS_LINK_DEST, QLatin1String("Dummy Link Target"));
 
389
            }
 
390
            listEntry(entry, false);
 
391
        }
 
392
        closedir( dp );
 
393
        listEntry( entry, true ); // ready
 
394
    } else {
 
395
        while ( ( ep = KDE_readdir( dp ) ) != 0 ) {
 
396
            entryNames.append( ep->d_name );
 
397
        }
 
398
 
 
399
        closedir( dp );
 
400
        totalSize( entryNames.count() );
 
401
 
 
402
        /* set the current dir to the path to speed up
 
403
           in not having to pass an absolute path.
 
404
           We restore the path later to get out of the
 
405
           path - the kernel wouldn't unmount or delete
 
406
           directories we keep as active directory. And
 
407
           as the slave runs in the background, it's hard
 
408
           to see for the user what the problem would be */
 
409
#if !defined(PATH_MAX) && defined(__GLIBC__)
 
410
        char *path_buffer = ::get_current_dir_name();
 
411
        const KDEPrivate::CharArrayDeleter path_buffer_deleter(path_buffer);
 
412
#else
 
413
        char path_buffer[PATH_MAX];
 
414
        path_buffer[0] = '\0';
 
415
        (void) getcwd(path_buffer, PATH_MAX - 1);
 
416
#endif
 
417
        if ( chdir( _path.data() ) )  {
 
418
            if (errno == EACCES)
 
419
                error(ERR_ACCESS_DENIED, path);
 
420
            else
 
421
                error(ERR_CANNOT_ENTER_DIRECTORY, path);
 
422
            finished();
 
423
        }
 
424
 
 
425
        QList<QByteArray>::ConstIterator it = entryNames.constBegin();
 
426
        QList<QByteArray>::ConstIterator end = entryNames.constEnd();
 
427
        for (; it != end; ++it) {
 
428
            entry.clear();
 
429
            if ( createUDSEntry( QFile::decodeName(*it),
 
430
                                 *it /* we can use the filename as relative path*/,
 
431
                                 entry, details, true ) )
 
432
                listEntry( entry, false);
 
433
        }
 
434
 
 
435
        listEntry( entry, true ); // ready
 
436
 
 
437
        //kDebug(7101) << "============= COMPLETED LIST ============";
 
438
 
 
439
#if !defined(PATH_MAX) && defined(__GLIBC__)
 
440
        if (path_buffer)
 
441
#else
 
442
        if (*path_buffer)
 
443
#endif
 
444
        {
 
445
            chdir(path_buffer);
 
446
        }
 
447
    }
 
448
    finished();
 
449
}
 
450
 
 
451
void FileProtocol::rename( const KUrl &srcUrl, const KUrl &destUrl,
 
452
                           KIO::JobFlags _flags )
 
453
{
 
454
    char off_t_should_be_64_bits[sizeof(off_t) >= 8 ? 1 : -1]; (void) off_t_should_be_64_bits;
 
455
    const QString src = srcUrl.toLocalFile();
 
456
    const QString dest = destUrl.toLocalFile();
 
457
    const QByteArray _src(QFile::encodeName(src));
 
458
    const QByteArray _dest(QFile::encodeName(dest));
 
459
    KDE_struct_stat buff_src;
 
460
    if ( KDE_lstat( _src.data(), &buff_src ) == -1 ) {
 
461
        if ( errno == EACCES )
 
462
           error(KIO::ERR_ACCESS_DENIED, src);
 
463
        else
 
464
           error(KIO::ERR_DOES_NOT_EXIST, src);
 
465
        return;
 
466
    }
 
467
 
 
468
    KDE_struct_stat buff_dest;
 
469
    // stat symlinks here (lstat, not stat), to avoid ERR_IDENTICAL_FILES when replacing symlink
 
470
    // with its target (#169547)
 
471
    bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
 
472
    if ( dest_exists )
 
473
    {
 
474
        if (S_ISDIR(buff_dest.st_mode))
 
475
        {
 
476
           error(KIO::ERR_DIR_ALREADY_EXIST, dest);
 
477
           return;
 
478
        }
 
479
 
 
480
        if ( same_inode( buff_dest, buff_src) )
 
481
        {
 
482
            error(KIO::ERR_IDENTICAL_FILES, dest);
 
483
            return;
 
484
        }
 
485
 
 
486
        if (!(_flags & KIO::Overwrite))
 
487
        {
 
488
           error(KIO::ERR_FILE_ALREADY_EXIST, dest);
 
489
           return;
 
490
        }
 
491
    }
 
492
 
 
493
    if ( KDE_rename( _src.data(), _dest.data()))
 
494
    {
 
495
        if (( errno == EACCES ) || (errno == EPERM)) {
 
496
            error(KIO::ERR_ACCESS_DENIED, dest);
 
497
        }
 
498
        else if (errno == EXDEV) {
 
499
           error(KIO::ERR_UNSUPPORTED_ACTION, QLatin1String("rename"));
 
500
        }
 
501
        else if (errno == EROFS) { // The file is on a read-only filesystem
 
502
           error(KIO::ERR_CANNOT_DELETE, src);
 
503
        }
 
504
        else {
 
505
           error(KIO::ERR_CANNOT_RENAME, src);
 
506
        }
 
507
        return;
 
508
    }
 
509
 
 
510
    finished();
 
511
}
 
512
 
 
513
void FileProtocol::symlink( const QString &target, const KUrl &destUrl, KIO::JobFlags flags )
 
514
{
 
515
    const QString dest = destUrl.toLocalFile();
 
516
    // Assume dest is local too (wouldn't be here otherwise)
 
517
    if ( ::symlink( QFile::encodeName(target), QFile::encodeName(dest) ) == -1 )
 
518
    {
 
519
        // Does the destination already exist ?
 
520
        if ( errno == EEXIST )
 
521
        {
 
522
            if ( (flags & KIO::Overwrite) )
 
523
            {
 
524
                // Try to delete the destination
 
525
                if ( unlink( QFile::encodeName(dest) ) != 0 )
 
526
                {
 
527
                    error(KIO::ERR_CANNOT_DELETE, dest);
 
528
                    return;
 
529
                }
 
530
                // Try again - this won't loop forever since unlink succeeded
 
531
                symlink( target, destUrl, flags );
 
532
            }
 
533
            else
 
534
            {
 
535
                KDE_struct_stat buff_dest;
 
536
                KDE_lstat( QFile::encodeName(dest), &buff_dest );
 
537
                if (S_ISDIR(buff_dest.st_mode))
 
538
                    error(KIO::ERR_DIR_ALREADY_EXIST, dest);
 
539
                else
 
540
                    error(KIO::ERR_FILE_ALREADY_EXIST, dest);
 
541
                return;
 
542
            }
 
543
        }
 
544
        else
 
545
        {
 
546
            // Some error occurred while we tried to symlink
 
547
            error(KIO::ERR_CANNOT_SYMLINK, dest);
 
548
            return;
 
549
        }
 
550
    }
 
551
    finished();
 
552
}
 
553
 
 
554
void FileProtocol::del(const KUrl& url, bool isfile)
 
555
{
 
556
    const QString path = url.toLocalFile();
 
557
    const QByteArray _path( QFile::encodeName(path));
 
558
    /*****
 
559
     * Delete files
 
560
     *****/
 
561
 
 
562
    if (isfile) {
 
563
        kDebug(7101) << "Deleting file "<< url;
 
564
 
 
565
        if ( unlink( _path.data() ) == -1 ) {
 
566
            if ((errno == EACCES) || (errno == EPERM))
 
567
               error(KIO::ERR_ACCESS_DENIED, path);
 
568
            else if (errno == EISDIR)
 
569
               error(KIO::ERR_IS_DIRECTORY, path);
 
570
            else
 
571
               error(KIO::ERR_CANNOT_DELETE, path);
 
572
            return;
 
573
        }
 
574
    } else {
 
575
 
 
576
      /*****
 
577
       * Delete empty directory
 
578
       *****/
 
579
 
 
580
      kDebug( 7101 ) << "Deleting directory " << url.url();
 
581
      if (metaData(QLatin1String("recurse")) == QLatin1String("true")) {
 
582
          if (!deleteRecursive(path))
 
583
              return;
 
584
      }
 
585
      if ( ::rmdir( _path.data() ) == -1 ) {
 
586
        if ((errno == EACCES) || (errno == EPERM))
 
587
          error(KIO::ERR_ACCESS_DENIED, path);
 
588
        else {
 
589
          kDebug( 7101 ) << "could not rmdir " << perror;
 
590
          error(KIO::ERR_COULD_NOT_RMDIR, path);
 
591
          return;
 
592
        }
 
593
      }
 
594
    }
 
595
 
 
596
    finished();
 
597
}
 
598
 
 
599
void FileProtocol::chown( const KUrl& url, const QString& owner, const QString& group )
 
600
{
 
601
    const QString path = url.toLocalFile();
 
602
    const QByteArray _path( QFile::encodeName(path) );
 
603
    uid_t uid;
 
604
    gid_t gid;
 
605
 
 
606
    // get uid from given owner
 
607
    {
 
608
        struct passwd *p = ::getpwnam(owner.toAscii());
 
609
 
 
610
        if ( ! p ) {
 
611
            error( KIO::ERR_SLAVE_DEFINED,
 
612
                   i18n( "Could not get user id for given user name %1", owner ) );
 
613
            return;
 
614
        }
 
615
 
 
616
        uid = p->pw_uid;
 
617
    }
 
618
 
 
619
    // get gid from given group
 
620
    {
 
621
        struct group *p = ::getgrnam(group.toAscii());
 
622
 
 
623
        if ( ! p ) {
 
624
            error( KIO::ERR_SLAVE_DEFINED,
 
625
                   i18n( "Could not get group id for given group name %1", group ) );
 
626
            return;
 
627
        }
 
628
 
 
629
        gid = p->gr_gid;
 
630
    }
 
631
 
 
632
    if ( ::chown(_path, uid, gid) == -1 ) {
 
633
        switch ( errno ) {
 
634
            case EPERM:
 
635
            case EACCES:
 
636
                error(KIO::ERR_ACCESS_DENIED, path);
 
637
                break;
 
638
            case ENOSPC:
 
639
                error(KIO::ERR_DISK_FULL, path);
 
640
                break;
 
641
            default:
 
642
                error(KIO::ERR_CANNOT_CHOWN, path);
 
643
        }
 
644
    } else
 
645
        finished();
 
646
}
 
647
 
 
648
void FileProtocol::stat( const KUrl & url )
 
649
{
 
650
    if (!url.isLocalFile()) {
 
651
        KUrl redir(url);
 
652
        redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
 
653
        redirection(redir);
 
654
        kDebug(7101) << "redirecting to " << redir.url();
 
655
        finished();
 
656
        return;
 
657
    }
 
658
 
 
659
    /* directories may not have a slash at the end if
 
660
     * we want to stat() them; it requires that we
 
661
     * change into it .. which may not be allowed
 
662
     * stat("/is/unaccessible")  -> rwx------
 
663
     * stat("/is/unaccessible/") -> EPERM            H.Z.
 
664
     * This is the reason for the -1
 
665
     */
 
666
    const QString path(url.path(KUrl::RemoveTrailingSlash));
 
667
    const QByteArray _path( QFile::encodeName(path));
 
668
    const QString sDetails = metaData(QLatin1String("details"));
 
669
    const int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
 
670
 
 
671
    UDSEntry entry;
 
672
    if ( !createUDSEntry( url.fileName(), _path, entry, details, true /*with acls*/ ) )
 
673
    {
 
674
        error(KIO::ERR_DOES_NOT_EXIST, path);
 
675
        return;
 
676
    }
 
677
#if 0
 
678
///////// debug code
 
679
    MetaData::iterator it1 = mOutgoingMetaData.begin();
 
680
    for ( ; it1 != mOutgoingMetaData.end(); it1++ ) {
 
681
        kDebug(7101) << it1.key() << " = " << it1.data();
 
682
    }
 
683
/////////
 
684
#endif
 
685
    statEntry( entry );
 
686
 
 
687
    finished();
 
688
}