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