]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/filedir.c
Use the right type for AFP function buffers size, size_t not int or unsigned int
[netatalk.git] / etc / afpd / filedir.c
1 /*
2  * $Id: filedir.c,v 1.58 2009-10-15 10:43:13 didg Exp $
3  *
4  * Copyright (c) 1990,1993 Regents of The University of Michigan.
5  * All Rights Reserved.  See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 /* STDC check */
15 #if STDC_HEADERS
16 #include <string.h>
17 #else /* STDC_HEADERS */
18 #ifndef HAVE_STRCHR
19 #define strchr index
20 #define strrchr index
21 #endif /* HAVE_STRCHR */
22 char *strchr (), *strrchr ();
23 #ifndef HAVE_MEMCPY
24 #define memcpy(d,s,n) bcopy ((s), (d), (n))
25 #define memmove(d,s,n) bcopy ((s), (d), (n))
26 #endif /* ! HAVE_MEMCPY */
27 #endif /* STDC_HEADERS */
28
29 #ifdef HAVE_STRINGS_H
30 #include <strings.h>
31 #endif
32 #include <dirent.h>
33 #include <errno.h>
34 #include <sys/param.h>
35
36 #include <atalk/adouble.h>
37 #include <atalk/vfs.h>
38 #include <atalk/afp.h>
39 #include <atalk/util.h>
40 #include <atalk/cnid.h>
41 #include <atalk/logger.h>
42
43 #include "directory.h"
44 #include "desktop.h"
45 #include "volume.h"
46 #include "fork.h"
47 #include "file.h"
48 #include "globals.h"
49 #include "filedir.h"
50 #include "unix.h"
51
52 #ifdef DROPKLUDGE
53 int matchfile2dirperms(
54 /* Since it's kinda' big; I decided against an
55 inline function */
56     char        *upath,
57     struct vol  *vol,
58     int         did)
59 /* The below code changes the way file ownership is determined in the name of
60 fixing dropboxes.  It has known security problem.  See the netatalk FAQ for
61 more information */
62 {
63     struct stat st, sb;
64     struct dir  *dir;
65     char        *adpath;
66     uid_t       uid;
67     int         ret = AFP_OK;
68 #ifdef DEBUG
69     LOG(log_info, logtype_afpd, "begin matchfile2dirperms:");
70 #endif /* DEBUG */
71
72     if (stat(upath, &st ) < 0) {
73         LOG(log_error, logtype_afpd, "Could not stat %s: %s", upath, strerror(errno));
74         return AFPERR_NOOBJ ;
75     }
76
77     adpath = vol->vfs->ad_path( upath, ADFLAGS_HF );
78     /* FIXME dirsearch doesn't move cwd to did ! */
79     if (( dir = dirlookup( vol, did )) == NULL ) {
80         LOG(log_error, logtype_afpd, "matchfile2dirperms: Unable to get directory info.");
81         ret = AFPERR_NOOBJ;
82     }
83     else if (stat(".", &sb) < 0) {
84         LOG(log_error, logtype_afpd,
85             "matchfile2dirperms: Error checking directory \"%s\": %s",
86             dir->d_m_name, strerror(errno));
87         ret = AFPERR_NOOBJ;
88     }
89     else {
90         uid=geteuid();
91         if ( uid != sb.st_uid )
92         {
93             seteuid(0);
94             if (lchown(upath, sb.st_uid, sb.st_gid) < 0)
95             {
96                 LOG(log_error, logtype_afpd,
97                     "matchfile2dirperms(%s): Error changing owner/gid: %s",
98                     upath, strerror(errno));
99                 ret = AFPERR_ACCESS;
100             }
101             else if (chmod(upath,(st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0)
102             {
103                 LOG(log_error, logtype_afpd,
104                     "matchfile2dirperms(%s): Error adding file read permissions: %s",
105                     upath, strerror(errno));
106                 ret = AFPERR_ACCESS;
107             }
108             else if (lchown(adpath, sb.st_uid, sb.st_gid) < 0)
109             {
110                 LOG(log_error, logtype_afpd,
111                     "matchfile2dirperms(%s): Error changing AppleDouble owner/gid: %s",
112                     adpath, strerror(errno));
113                 ret = AFPERR_ACCESS;
114             }
115             else if (chmod(adpath, (st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0)
116             {
117                 LOG(log_error, logtype_afpd,
118                     "matchfile2dirperms(%s):  Error adding AD file read permissions: %s",
119                     adpath, strerror(errno));
120                 ret = AFPERR_ACCESS;
121             }
122             seteuid(uid); 
123         }
124     } /* end else if stat success */
125
126 #ifdef DEBUG
127     LOG(log_info, logtype_afpd, "end matchfile2dirperms:");
128 #endif /* DEBUG */
129     return ret;
130 }
131 #endif
132
133 int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
134 {
135     struct stat         *st;
136     struct vol          *vol;
137     struct dir          *dir;
138     u_int32_t           did;
139     int                 ret;
140     size_t              buflen;
141     u_int16_t           fbitmap, dbitmap, vid;
142     struct path         *s_path;
143
144 #ifdef DEBUG
145     LOG(log_info, logtype_afpd, "begin afp_getfildirparams:");
146 #endif /* DEBUG */
147
148     *rbuflen = 0;
149     ibuf += 2;
150
151     memcpy( &vid, ibuf, sizeof( vid ));
152     ibuf += sizeof( vid );
153     if (NULL == ( vol = getvolbyvid( vid )) ) {
154         /* was AFPERR_PARAM but it helps OS 10.3 when a volume has been removed
155          * from the list.
156          */ 
157         return( AFPERR_ACCESS );
158     }
159
160     memcpy( &did, ibuf, sizeof( did ));
161     ibuf += sizeof( did );
162
163     if (NULL == ( dir = dirlookup( vol, did )) ) {
164         return afp_errno;
165     }
166
167     memcpy( &fbitmap, ibuf, sizeof( fbitmap ));
168     fbitmap = ntohs( fbitmap );
169     ibuf += sizeof( fbitmap );
170     memcpy( &dbitmap, ibuf, sizeof( dbitmap ));
171     dbitmap = ntohs( dbitmap );
172     ibuf += sizeof( dbitmap );
173
174     if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
175         return get_afp_errno(AFPERR_NOOBJ); 
176     }
177
178     st   = &s_path->st;
179     if (!s_path->st_valid) {
180         /* it's a dir and it should be there
181          * because we chdir in it in cname or
182          * it's curdir (maybe deleted, but then we can't know).
183          * So we need to try harder.
184          */
185         of_statdir(vol, s_path);
186     }
187     if ( s_path->st_errno != 0 ) {
188         return( AFPERR_NOOBJ );
189     }
190
191     buflen = 0;
192     if (S_ISDIR(st->st_mode)) {
193         if (dbitmap) {
194             dir = s_path->d_dir;
195             if (!dir) 
196                 return AFPERR_NOOBJ;
197
198             ret = getdirparams(vol, dbitmap, s_path, dir,
199                                  rbuf + 3 * sizeof( u_int16_t ), &buflen );
200             if (ret != AFP_OK )
201                 return( ret );
202         }
203         /* this is a directory */
204         *(rbuf + 2 * sizeof( u_int16_t )) = (char) FILDIRBIT_ISDIR;
205     } else {
206         if (fbitmap && AFP_OK != (ret = getfilparams(vol, fbitmap, s_path, curdir, 
207                                             rbuf + 3 * sizeof( u_int16_t ), &buflen )) ) {
208             return( ret );
209         }
210         /* this is a file */
211         *(rbuf + 2 * sizeof( u_int16_t )) = FILDIRBIT_ISFILE;
212     }
213     *rbuflen = buflen + 3 * sizeof( u_int16_t );
214     fbitmap = htons( fbitmap );
215     memcpy( rbuf, &fbitmap, sizeof( fbitmap ));
216     rbuf += sizeof( fbitmap );
217     dbitmap = htons( dbitmap );
218     memcpy( rbuf, &dbitmap, sizeof( dbitmap ));
219     rbuf += sizeof( dbitmap ) + sizeof( u_char );
220     *rbuf = 0;
221
222 #ifdef DEBUG
223     LOG(log_info, logtype_afpd, "end afp_getfildirparams:");
224 #endif /* DEBUG */
225
226     return( AFP_OK );
227 }
228
229 int afp_setfildirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
230 {
231     struct stat *st;
232     struct vol  *vol;
233     struct dir  *dir;
234     struct path *path;
235     u_int16_t   vid, bitmap;
236     int         did, rc;
237
238 #ifdef DEBUG
239     LOG(log_info, logtype_afpd, "begin afp_setfildirparams:");
240 #endif /* DEBUG */
241
242     *rbuflen = 0;
243     ibuf += 2;
244     memcpy( &vid, ibuf, sizeof(vid));
245     ibuf += sizeof( vid );
246
247     if (NULL == ( vol = getvolbyvid( vid )) ) {
248         return( AFPERR_PARAM );
249     }
250
251     if (vol->v_flags & AFPVOL_RO)
252         return AFPERR_VLOCK;
253
254     memcpy( &did, ibuf, sizeof( did));
255     ibuf += sizeof( did);
256
257     if (NULL == ( dir = dirlookup( vol, did )) ) {
258         return afp_errno;    
259     }
260
261     memcpy( &bitmap, ibuf, sizeof( bitmap ));
262     bitmap = ntohs( bitmap );
263     ibuf += sizeof( bitmap );
264
265     if (NULL == ( path = cname( vol, dir, &ibuf ))) {
266         return get_afp_errno(AFPERR_NOOBJ); 
267     }
268
269     st   = &path->st;
270     if (!path->st_valid) {
271         /* it's a dir and it should be there
272          * because we chdir in it in cname
273          */
274         of_statdir(vol, path);
275     }
276
277     if ( path->st_errno != 0 ) {
278         return( AFPERR_NOOBJ );
279     }
280     /*
281      * If ibuf is odd, make it even.
282      */
283     if ((u_long)ibuf & 1 ) {
284         ibuf++;
285     }
286
287     if (S_ISDIR(st->st_mode)) {
288         rc = setdirparams(vol, path, bitmap, ibuf );
289     } else {
290         rc = setfilparams(vol, path, bitmap, ibuf );
291     }
292     if ( rc == AFP_OK ) {
293         setvoltime(obj, vol );
294     }
295
296 #ifdef DEBUG
297     LOG(log_info, logtype_afpd, "end afp_setfildirparams:");
298 #endif /* DEBUG */
299
300     return( rc );
301 }
302
303 /* -------------------------------------------- 
304    Factorise some checks on a pathname
305 */
306 int check_name(const struct vol *vol, char *name)
307 {
308     /* check for illegal characters in the unix filename */
309     if (!wincheck(vol, name))
310         return AFPERR_PARAM;
311
312     if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/'))
313         return AFPERR_PARAM;
314
315     if (!vol->vfs->vfs_validupath(vol, name)) {
316         LOG(log_info, logtype_afpd, "check_name: illegal name: '%s'", name);
317         return AFPERR_EXIST;
318     }
319
320     /* check for vetoed filenames */
321     if (veto_file(vol->v_veto, name))
322         return AFPERR_EXIST;
323     return 0;
324 }
325
326 /* ------------------------- 
327     move and rename sdir:oldname to curdir:newname in volume vol
328    
329     special care is needed for lock   
330 */
331 static int moveandrename(const struct vol *vol, struct dir *sdir, char *oldname, char *newname, int isdir)
332 {
333     char            *p;
334     char            *upath;
335     int             rc;
336     struct stat     *st, nst;
337     int             adflags;
338     struct adouble      ad;
339     struct adouble      *adp;
340     struct ofork        *opened = NULL;
341     struct path         path;
342     cnid_t      id;
343
344     ad_init(&ad, vol->v_adouble, vol->v_ad_options);
345     adp = &ad;
346     adflags = 0;
347     
348     if (!isdir) {
349         p = mtoupath(vol, oldname, sdir->d_did, utf8_encoding());
350         if (!p) { 
351             return AFPERR_PARAM; /* can't convert */
352         }
353         id = cnid_get(vol->v_cdb, sdir->d_did, p, strlen(p));
354         p = ctoupath( vol, sdir, oldname );
355         if (!p) { 
356             return AFPERR_PARAM; /* pathname too long */
357         }
358         path.st_valid = 0;
359         path.u_name = p;
360         if ((opened = of_findname(&path))) {
361             /* reuse struct adouble so it won't break locks */
362             adp = opened->of_ad;
363         }
364     }
365     else {
366         id = sdir->d_did; /* we already have the CNID */
367         p = ctoupath( vol, sdir->d_parent, oldname );
368         if (!p) {
369             return AFPERR_PARAM;
370         }
371         adflags = ADFLAGS_DIR;
372     }
373     /*
374      * p now points to the full pathname of the source fs object.
375      * 
376      * we are in the dest folder so we need to use p for ad_open
377     */
378     
379     if (!ad_metadata(p, adflags, adp)) {
380         u_int16_t bshort;
381
382         ad_getattr(adp, &bshort);
383         ad_close_metadata( adp);
384         if ((bshort & htons(ATTRBIT_NORENAME))) 
385             return(AFPERR_OLOCK);
386     }
387
388     if (NULL == (upath = mtoupath(vol, newname, curdir->d_did, utf8_encoding()))){ 
389         return AFPERR_PARAM;
390     }
391     path.u_name = upath;
392     st = &path.st;    
393     if (0 != (rc = check_name(vol, upath))) {
394             return  rc;
395     }
396
397     /* source == destination. we just silently accept this. */
398     if ((!isdir && curdir == sdir) || (isdir && curdir == sdir->d_parent)) {
399         if (strcmp(oldname, newname) == 0)
400             return AFP_OK;
401
402         if (stat(upath, st) == 0 || caseenumerate(vol, &path, curdir) == 0) {
403             if (!stat(p, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) {
404                 /* not the same file */
405                 return AFPERR_EXIST;
406             }
407             errno = 0;
408         }
409     } else if (stat(upath, st ) == 0 || caseenumerate(vol, &path, curdir) == 0)
410         return AFPERR_EXIST;
411
412     if ( !isdir ) {
413         path.st_valid = 1;
414         path.st_errno = errno;
415         if (of_findname(&path)) {
416             rc = AFPERR_EXIST; /* was AFPERR_BUSY; */
417         } else {
418             rc = renamefile(vol, p, upath, newname, adp );
419             if (rc == AFP_OK)
420                 of_rename(vol, opened, sdir, oldname, curdir, newname);
421         }
422     } else {
423         rc = renamedir(vol, p, upath, sdir, curdir, newname);
424     }
425     if ( rc == AFP_OK && id ) {
426         /* renaming may have moved the file/dir across a filesystem */
427         if (stat(upath, st) < 0)
428             return AFPERR_MISC;
429
430         /* fix up the catalog entry */
431         cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath));
432     }
433
434     return rc;
435 }
436
437 /* -------------------------------------------- */
438 int afp_rename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
439 {
440     struct vol  *vol;
441     struct dir  *sdir;
442     char        *oldname, *newname;
443     struct path *path;
444     u_int32_t   did;
445     int         plen;
446     u_int16_t   vid;
447     int         isdir = 0;
448     int         rc;
449 #ifdef DEBUG
450     LOG(log_info, logtype_afpd, "begin afp_rename:");
451 #endif /* DEBUG */
452
453     *rbuflen = 0;
454     ibuf += 2;
455
456     memcpy( &vid, ibuf, sizeof( vid ));
457     ibuf += sizeof( vid );
458     if (NULL == ( vol = getvolbyvid( vid )) ) {
459         return( AFPERR_PARAM );
460     }
461
462     if (vol->v_flags & AFPVOL_RO)
463         return AFPERR_VLOCK;
464
465     memcpy( &did, ibuf, sizeof( did ));
466     ibuf += sizeof( did );
467     if (NULL == ( sdir = dirlookup( vol, did )) ) {
468         return afp_errno;    
469     }
470
471     /* source pathname */
472     if (NULL == ( path = cname( vol, sdir, &ibuf )) ) {
473         return get_afp_errno(AFPERR_NOOBJ); 
474     }
475
476     sdir = curdir;
477     newname = obj->newtmp;
478     oldname = obj->oldtmp;
479     isdir = path_isadir(path);
480     if ( *path->m_name != '\0' ) {
481         strcpy(oldname, path->m_name); /* an extra copy for of_rename */
482         if (isdir) {
483             /* curdir parent dir, need to move sdir back */
484             sdir = path->d_dir;
485         }
486     }
487     else {
488         if ( sdir->d_parent == NULL ) { /* root directory */
489             return( AFPERR_NORENAME );
490         }
491         /* move to destination dir */
492         if ( movecwd( vol, sdir->d_parent ) < 0 ) {
493             return afp_errno;
494         }
495         strcpy(oldname, sdir->d_m_name);
496     }
497
498     /* another place where we know about the path type */
499     if ((plen = copy_path_name(vol, newname, ibuf)) < 0) {
500         return( AFPERR_PARAM );
501     }
502
503     if (!plen) {
504         return AFP_OK; /* newname == oldname same dir */
505     }
506     
507     rc = moveandrename(vol, sdir, oldname, newname, isdir);
508
509     if ( rc == AFP_OK ) {
510         setvoltime(obj, vol );
511     }
512
513 #ifdef DEBUG
514     LOG(log_info, logtype_afpd, "end afp_rename:");
515 #endif /* DEBUG */
516
517     return( rc );
518 }
519
520 /* ------------------------------- */
521 int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
522 {
523     struct vol          *vol;
524     struct dir          *dir;
525     struct path         *s_path;
526     char                *upath;
527     int                 did, rc;
528     u_int16_t           vid;
529
530 #ifdef DEBUG
531     LOG(log_info, logtype_afpd, "begin afp_delete:");
532 #endif /* DEBUG */ 
533
534     *rbuflen = 0;
535     ibuf += 2;
536
537     memcpy( &vid, ibuf, sizeof( vid ));
538     ibuf += sizeof( vid );
539     if (NULL == ( vol = getvolbyvid( vid )) ) {
540         return( AFPERR_PARAM );
541     }
542
543     if (vol->v_flags & AFPVOL_RO)
544         return AFPERR_VLOCK;
545
546     memcpy( &did, ibuf, sizeof( did ));
547     ibuf += sizeof( int );
548     if (NULL == ( dir = dirlookup( vol, did )) ) {
549         return afp_errno;    
550     }
551
552     if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
553         return get_afp_errno(AFPERR_NOOBJ); 
554     }
555
556     upath = s_path->u_name;
557     if ( path_isadir( s_path) ) {
558         if (*s_path->m_name != '\0') {
559             rc = AFPERR_ACCESS;
560         }
561         else {
562             rc = deletecurdir( vol);
563         }
564     } else if (of_findname(s_path)) {
565         rc = AFPERR_BUSY;
566     } else {
567         rc = deletefile(vol, upath, 1);
568     }
569     if ( rc == AFP_OK ) {
570         curdir->offcnt--;
571         setvoltime(obj, vol );
572     }
573
574 #ifdef DEBUG
575     LOG(log_info, logtype_afpd, "end afp_delete:");
576 #endif /* DEBUG */
577
578     return( rc );
579 }
580 /* ------------------------ */
581 char *absupath(const struct vol *vol, struct dir *dir, char *u)
582 {
583     struct dir  *d;
584     static char path[ MAXPATHLEN + 1];
585     char        *p;
586     int         len;
587
588     if (u == NULL)
589         return NULL;
590         
591     p = path + sizeof( path ) - 1;
592     *p = '\0';
593     len = strlen( u );
594     p -= len;
595     memcpy( p, u, len );
596     if (dir) for ( d = dir; d->d_parent; d = d->d_parent ) {
597         u = d->d_u_name;
598         len = strlen( u );
599         if (p -len -1 < path) {
600             /* FIXME 
601                rather rare so LOG error and/or client message ?
602             */
603             return NULL;
604         }
605         *--p = '/';
606         p -= len;
607         memcpy( p, u, len );
608     }
609     len = strlen( vol->v_path );
610     if (p -len -1 < path) {
611         return NULL;
612     }
613     *--p = '/';
614     p -= len;
615     memcpy( p, vol->v_path, len );
616
617     return( p );
618 }
619
620 /* ------------------------
621  * FIXME dir could be NULL
622 */
623 char *ctoupath(const struct vol *vol, struct dir *dir, char *name)
624 {
625     return absupath(vol, dir, mtoupath(vol, name, dir->d_did, utf8_encoding()));
626 }
627
628 /* ------------------------- */
629 int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
630 {
631     struct vol  *vol;
632     struct dir  *sdir, *ddir;
633     int         isdir;
634     char        *oldname, *newname;
635     struct path *path;
636     int         did;
637     int         pdid;
638     int         plen;
639     u_int16_t   vid;
640     int         rc;
641 #ifdef DROPKLUDGE
642     int         retvalue;
643 #endif /* DROPKLUDGE */
644
645 #ifdef DEBUG
646     LOG(log_info, logtype_afpd, "begin afp_moveandrename:");
647 #endif /* DEBUG */
648
649     *rbuflen = 0;
650     ibuf += 2;
651
652     memcpy( &vid, ibuf, sizeof( vid ));
653     ibuf += sizeof( vid );
654     if (NULL == ( vol = getvolbyvid( vid )) ) {
655         return( AFPERR_PARAM );
656     }
657
658     if (vol->v_flags & AFPVOL_RO)
659         return AFPERR_VLOCK;
660
661     /* source did followed by dest did */
662     memcpy( &did, ibuf, sizeof( did ));
663     ibuf += sizeof( int );
664     if (NULL == ( sdir = dirlookup( vol, did )) ) {
665         return afp_errno; /* was AFPERR_PARAM */
666     }
667
668     memcpy( &did, ibuf, sizeof( did ));
669     ibuf += sizeof( int );
670
671     /* source pathname */
672     if (NULL == ( path = cname( vol, sdir, &ibuf )) ) {
673         return get_afp_errno(AFPERR_NOOBJ); 
674     }
675
676     sdir = curdir;
677     newname = obj->newtmp;
678     oldname = obj->oldtmp;
679     
680     isdir = path_isadir(path);
681     if ( *path->m_name != '\0' ) {
682         if (isdir) {
683             sdir = path->d_dir;
684         }
685         strcpy(oldname, path->m_name); /* an extra copy for of_rename */
686     } else {
687         strcpy(oldname, sdir->d_m_name);
688     }
689
690     /* get the destination directory */
691     if (NULL == ( ddir = dirlookup( vol, did )) ) {
692         return afp_errno; /*  was AFPERR_PARAM */
693     }
694     if (NULL == ( path = cname( vol, ddir, &ibuf ))) {
695         return( AFPERR_NOOBJ );
696     }
697     pdid = curdir->d_did;
698     if ( *path->m_name != '\0' ) {
699         return path_error(path, AFPERR_NOOBJ);
700     }
701
702     /* one more place where we know about path type */
703     if ((plen = copy_path_name(vol, newname, ibuf)) < 0) {
704         return( AFPERR_PARAM );
705     }
706
707     if (!plen) {
708         strcpy(newname, oldname);
709     }
710
711     rc = moveandrename(vol, sdir, oldname, newname, isdir);
712
713     if ( rc == AFP_OK ) {
714         char *upath = mtoupath(vol, newname, pdid, utf8_encoding());
715         
716         if (NULL == upath) {
717             return AFPERR_PARAM;
718         }
719         curdir->offcnt++;
720         sdir->offcnt--;
721 #ifdef DROPKLUDGE
722         if (vol->v_flags & AFPVOL_DROPBOX) {
723             /* FIXME did is not always the source id */
724             if ((retvalue=matchfile2dirperms (upath, vol, did)) != AFP_OK) {
725                 return retvalue;
726             }
727         }
728         else
729 #endif /* DROPKLUDGE */
730             /* if unix priv don't try to match perm with dest folder */
731             if (!isdir && !vol_unix_priv(vol)) {
732                 int  admode = ad_mode("", 0777) | vol->v_fperm;
733
734                 setfilmode(upath, admode, NULL, vol->v_umask);
735                 vol->vfs->vfs_setfilmode(vol, upath, admode, NULL);
736             }
737         setvoltime(obj, vol );
738     }
739
740 #ifdef DEBUG
741     LOG(log_info, logtype_afpd, "end afp_moveandrename:");
742 #endif /* DEBUG */
743
744     return( rc );
745 }
746
747 int veto_file(const char*veto_str, const char*path)
748 /* given a veto_str like "abc/zxc/" and path "abc", return 1
749  * veto_str should be '/' delimited
750  * if path matches any one of the veto_str elements exactly, then 1 is returned
751  * otherwise, 0 is returned.
752  */
753 {
754     int i;      /* index to veto_str */
755     int j;      /* index to path */
756
757     if ((veto_str == NULL) || (path == NULL))
758         return 0;
759
760     for(i=0, j=0; veto_str[i] != '\0'; i++) {
761         if (veto_str[i] == '/') {
762             if ((j>0) && (path[j] == '\0')) {
763                 LOG(log_info, logtype_afpd, "vetoed file:'%s'", path);
764                 return 1;
765             }
766             j = 0;
767         } else {
768             if (veto_str[i] != path[j]) {
769                 while ((veto_str[i] != '/')
770                         && (veto_str[i] != '\0'))
771                     i++;
772                 j = 0;
773                 continue;
774             }
775             j++;
776         }
777     }
778     return 0;
779 }
780