~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source3/modules/vfs_crossrename.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) Björn Jacke 2010
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 3 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 
16
 */
 
17
 
 
18
#include "includes.h"
 
19
#include "smbd/smbd.h"
 
20
#include "system/filesys.h"
 
21
#include "transfer_file.h"
 
22
#include "smbprofile.h"
 
23
 
 
24
#define MODULE "crossrename"
 
25
static SMB_OFF_T module_sizelimit;
 
26
 
 
27
static int crossrename_connect(
 
28
                struct vfs_handle_struct *  handle,
 
29
                const char *                service,
 
30
                const char *                user)
 
31
{
 
32
        int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
 
33
 
 
34
        if (ret < 0) {
 
35
                return ret;
 
36
        }
 
37
 
 
38
        module_sizelimit = (SMB_OFF_T) lp_parm_int(SNUM(handle->conn),
 
39
                                        MODULE, "sizelimit", 20);
 
40
        /* convert from MiB to byte: */
 
41
        module_sizelimit *= 1048576;
 
42
 
 
43
        return 0;
 
44
}
 
45
 
 
46
/*********************************************************
 
47
 For rename across filesystems initial Patch from Warren Birnbaum
 
48
 <warrenb@hpcvscdp.cv.hp.com>
 
49
**********************************************************/
 
50
 
 
51
static int copy_reg(const char *source, const char *dest)
 
52
{
 
53
        SMB_STRUCT_STAT source_stats;
 
54
        int saved_errno;
 
55
        int ifd = -1;
 
56
        int ofd = -1;
 
57
 
 
58
        if (sys_lstat(source, &source_stats, false) == -1)
 
59
                return -1;
 
60
 
 
61
        if (!S_ISREG (source_stats.st_ex_mode))
 
62
                return -1;
 
63
 
 
64
        if (source_stats.st_ex_size > module_sizelimit) {
 
65
                DEBUG(5,
 
66
                        ("%s: size of %s larger than sizelimit (%lld > %lld), rename prohititted\n",
 
67
                        MODULE, source,
 
68
                        (long long)source_stats.st_ex_size,
 
69
                        (long long)module_sizelimit));
 
70
                return -1;
 
71
        }
 
72
 
 
73
        if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
 
74
                return -1;
 
75
 
 
76
        if (unlink (dest) && errno != ENOENT)
 
77
                return -1;
 
78
 
 
79
#ifdef O_NOFOLLOW
 
80
        if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
 
81
#else
 
82
        if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
 
83
#endif
 
84
                goto err;
 
85
 
 
86
        if (transfer_file(ifd, ofd, source_stats.st_ex_size) == -1)
 
87
                goto err;
 
88
 
 
89
        /*
 
90
         * Try to preserve ownership.  For non-root it might fail, but that's ok.
 
91
         * But root probably wants to know, e.g. if NFS disallows it.
 
92
         */
 
93
 
 
94
#ifdef HAVE_FCHOWN
 
95
        if ((fchown(ofd, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM))
 
96
#else
 
97
        if ((chown(dest, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM))
 
98
#endif
 
99
                goto err;
 
100
 
 
101
        /*
 
102
         * fchown turns off set[ug]id bits for non-root,
 
103
         * so do the chmod last.
 
104
         */
 
105
 
 
106
#if defined(HAVE_FCHMOD)
 
107
        if (fchmod (ofd, source_stats.st_ex_mode & 07777))
 
108
#else
 
109
        if (chmod (dest, source_stats.st_ex_mode & 07777))
 
110
#endif
 
111
                goto err;
 
112
 
 
113
        if (close (ifd) == -1)
 
114
                goto err;
 
115
 
 
116
        if (close (ofd) == -1)
 
117
                return -1;
 
118
 
 
119
        /* Try to copy the old file's modtime and access time.  */
 
120
#if defined(HAVE_UTIMENSAT)
 
121
        {
 
122
                struct timespec ts[2];
 
123
 
 
124
                ts[0] = source_stats.st_ex_atime;
 
125
                ts[1] = source_stats.st_ex_mtime;
 
126
                utimensat(AT_FDCWD, dest, ts, AT_SYMLINK_NOFOLLOW);
 
127
        }
 
128
#elif defined(HAVE_UTIMES)
 
129
        {
 
130
                struct timeval tv[2];
 
131
 
 
132
                tv[0] = convert_timespec_to_timeval(source_stats.st_ex_atime);
 
133
                tv[1] = convert_timespec_to_timeval(source_stats.st_ex_mtime);
 
134
#ifdef HAVE_LUTIMES
 
135
                lutimes(dest, tv);
 
136
#else
 
137
                utimes(dest, tv);
 
138
#endif
 
139
        }
 
140
#elif defined(HAVE_UTIME)
 
141
        {
 
142
                struct utimbuf tv;
 
143
 
 
144
                tv.actime = convert_timespec_to_time_t(source_stats.st_ex_atime);
 
145
                tv.modtime = convert_timespec_to_time_t(source_stats.st_ex_mtime);
 
146
                utime(dest, &tv);
 
147
        }
 
148
#endif
 
149
 
 
150
        if (unlink (source) == -1)
 
151
                return -1;
 
152
 
 
153
        return 0;
 
154
 
 
155
  err:
 
156
 
 
157
        saved_errno = errno;
 
158
        if (ifd != -1)
 
159
                close(ifd);
 
160
        if (ofd != -1)
 
161
                close(ofd);
 
162
        errno = saved_errno;
 
163
        return -1;
 
164
}
 
165
 
 
166
 
 
167
static int crossrename_rename(vfs_handle_struct *handle,
 
168
                          const struct smb_filename *smb_fname_src,
 
169
                          const struct smb_filename *smb_fname_dst)
 
170
{
 
171
        int result = -1;
 
172
 
 
173
        START_PROFILE(syscall_rename);
 
174
 
 
175
        if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
 
176
                errno = ENOENT;
 
177
                goto out;
 
178
        }
 
179
 
 
180
        result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
 
181
        if ((result == -1) && (errno == EXDEV)) {
 
182
                /* Rename across filesystems needed. */
 
183
                result = copy_reg(smb_fname_src->base_name,
 
184
                                  smb_fname_dst->base_name);
 
185
        }
 
186
 
 
187
 out:
 
188
        END_PROFILE(syscall_rename);
 
189
        return result;
 
190
}
 
191
 
 
192
static struct vfs_fn_pointers vfs_crossrename_fns = {
 
193
        .connect_fn = crossrename_connect,
 
194
        .rename = crossrename_rename
 
195
};
 
196
 
 
197
NTSTATUS vfs_crossrename_init(void);
 
198
NTSTATUS vfs_crossrename_init(void)
 
199
{
 
200
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE,
 
201
                                &vfs_crossrename_fns);
 
202
}
 
203