~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to etc/afpd/file.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: file.c,v 1.62.2.1 2003/06/09 14:53:15 srittau 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
#ifdef HAVE_UNISTD_H
 
15
#include <unistd.h>
 
16
#endif /* HAVE_UNISTD_H */
 
17
 
 
18
/* STDC check */
 
19
#if STDC_HEADERS
 
20
#include <string.h>
 
21
#else /* STDC_HEADERS */
 
22
#ifndef HAVE_STRCHR
 
23
#define strchr index
 
24
#define strrchr index
 
25
#endif /* HAVE_STRCHR */
 
26
char *strchr (), *strrchr ();
 
27
#ifndef HAVE_MEMCPY
 
28
#define memcpy(d,s,n) bcopy ((s), (d), (n))
 
29
#define memmove(d,s,n) bcopy ((s), (d), (n))
 
30
#endif /* ! HAVE_MEMCPY */
 
31
#endif /* STDC_HEADERS */
 
32
 
 
33
#include <utime.h>
 
34
#ifdef HAVE_FCNTL_H
 
35
#include <fcntl.h>
 
36
#endif /* HAVE_FCNTL_H */
 
37
#include <dirent.h>
 
38
#include <sys/mman.h>
 
39
#include <errno.h>
 
40
 
 
41
#include <atalk/logger.h>
 
42
#include <sys/types.h>
 
43
#include <sys/time.h>
 
44
#include <sys/param.h>
 
45
#include <sys/stat.h>
 
46
 
 
47
#include <netatalk/endian.h>
 
48
#include <atalk/adouble.h>
 
49
#include <atalk/afp.h>
 
50
#include <atalk/util.h>
 
51
#ifdef CNID_DB
 
52
#include <atalk/cnid.h>
 
53
#endif /* CNID_DB */
 
54
#include "directory.h"
 
55
#include "desktop.h"
 
56
#include "volume.h"
 
57
#include "fork.h"
 
58
#include "file.h"
 
59
#include "filedir.h"
 
60
#include "globals.h"
 
61
 
 
62
/* the format for the finderinfo fields (from IM: Toolbox Essentials):
 
63
 * field         bytes        subfield    bytes
 
64
 * 
 
65
 * files:
 
66
 * ioFlFndrInfo  16      ->       type    4  type field
 
67
 *                             creator    4  creator field
 
68
 *                               flags    2  finder flags:
 
69
 *                                           alias, bundle, etc.
 
70
 *                            location    4  location in window
 
71
 *                              folder    2  window that contains file
 
72
 * 
 
73
 * ioFlXFndrInfo 16      ->     iconID    2  icon id
 
74
 *                              unused    6  reserved 
 
75
 *                              script    1  script system
 
76
 *                              xflags    1  reserved
 
77
 *                           commentID    2  comment id
 
78
 *                           putawayID    4  home directory id
 
79
 */
 
80
 
 
81
const u_char ufinderi[] = {
 
82
                              'T', 'E', 'X', 'T', 'U', 'N', 'I', 'X',
 
83
                              0, 0, 0, 0, 0, 0, 0, 0,
 
84
                              0, 0, 0, 0, 0, 0, 0, 0,
 
85
                              0, 0, 0, 0, 0, 0, 0, 0
 
86
                          };
 
87
 
 
88
int getmetadata(struct vol *vol,
 
89
                 u_int16_t bitmap,
 
90
                 char *path, struct dir *dir, struct stat *st,
 
91
                 char *buf, int *buflen, struct adouble *adp, int attrbits )
 
92
{
 
93
#ifndef USE_LASTDID
 
94
    struct stat         lst, *lstp;
 
95
#endif /* USE_LASTDID */
 
96
    struct extmap       *em;
 
97
    char                *data, *nameoff = NULL, *upath;
 
98
    int                 bit = 0;
 
99
    u_int32_t           aint;
 
100
    u_int16_t           ashort;
 
101
    u_char              achar, fdType[4];
 
102
#if 0
 
103
    struct maccess      ma;
 
104
#endif
 
105
 
 
106
#ifdef DEBUG
 
107
    LOG(log_info, logtype_afpd, "begin getmetadata:");
 
108
#endif /* DEBUG */
 
109
 
 
110
    upath = mtoupath(vol, path);
 
111
 
 
112
    data = buf;
 
113
    while ( bitmap != 0 ) {
 
114
        while (( bitmap & 1 ) == 0 ) {
 
115
            bitmap = bitmap>>1;
 
116
            bit++;
 
117
        }
 
118
 
 
119
        switch ( bit ) {
 
120
        case FILPBIT_ATTR :
 
121
            if ( adp ) {
 
122
                ad_getattr(adp, &ashort);
 
123
            } else if (*upath == '.') {
 
124
                ashort = htons(ATTRBIT_INVISIBLE);
 
125
            } else
 
126
                ashort = 0;
 
127
#if 0
 
128
            /* FIXME do we want a visual clue if the file is read only
 
129
             */
 
130
            accessmode( ".", &ma, dir , NULL);
 
131
            if ((ma.ma_user & AR_UWRITE)) {
 
132
                accessmode( upath, &ma, dir , st);
 
133
                if (!(ma.ma_user & AR_UWRITE)) {
 
134
                        attrbits |= ATTRBIT_NOWRITE;
 
135
                }
 
136
            }
 
137
#endif
 
138
            if (attrbits)
 
139
                ashort = htons(ntohs(ashort) | attrbits);
 
140
            memcpy(data, &ashort, sizeof( ashort ));
 
141
            data += sizeof( ashort );
 
142
            break;
 
143
 
 
144
        case FILPBIT_PDID :
 
145
            memcpy(data, &dir->d_did, sizeof( u_int32_t ));
 
146
            data += sizeof( u_int32_t );
 
147
            break;
 
148
 
 
149
        case FILPBIT_CDATE :
 
150
            if (!adp || (ad_getdate(adp, AD_DATE_CREATE, &aint) < 0))
 
151
                aint = AD_DATE_FROM_UNIX(st->st_mtime);
 
152
            memcpy(data, &aint, sizeof( aint ));
 
153
            data += sizeof( aint );
 
154
            break;
 
155
 
 
156
        case FILPBIT_MDATE :
 
157
            if ( adp && (ad_getdate(adp, AD_DATE_MODIFY, &aint) == 0)) {
 
158
                if ((st->st_mtime > AD_DATE_TO_UNIX(aint))) {
 
159
                   aint = AD_DATE_FROM_UNIX(st->st_mtime);
 
160
                }
 
161
            } else {
 
162
                aint = AD_DATE_FROM_UNIX(st->st_mtime);
 
163
            }
 
164
            memcpy(data, &aint, sizeof( int ));
 
165
            data += sizeof( int );
 
166
            break;
 
167
 
 
168
        case FILPBIT_BDATE :
 
169
            if (!adp || (ad_getdate(adp, AD_DATE_BACKUP, &aint) < 0))
 
170
                aint = AD_DATE_START;
 
171
            memcpy(data, &aint, sizeof( int ));
 
172
            data += sizeof( int );
 
173
            break;
 
174
 
 
175
        case FILPBIT_FINFO :
 
176
            if (adp)
 
177
                memcpy(data, ad_entry(adp, ADEID_FINDERI), 32);
 
178
            else {
 
179
                memcpy(data, ufinderi, 32);
 
180
                if (*upath == '.') { /* make it invisible */
 
181
                    ashort = htons(FINDERINFO_INVISIBLE);
 
182
                    memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
 
183
                }
 
184
            }
 
185
 
 
186
            if ((!adp  || !memcmp(ad_entry(adp, ADEID_FINDERI),ufinderi , 8 )) 
 
187
                && (em = getextmap( path ))
 
188
            ) {
 
189
                memcpy(data, em->em_type, sizeof( em->em_type ));
 
190
                memcpy(data + 4, em->em_creator, sizeof(em->em_creator));
 
191
            }
 
192
            data += 32;
 
193
            break;
 
194
 
 
195
        case FILPBIT_LNAME :
 
196
            nameoff = data;
 
197
            data += sizeof( u_int16_t );
 
198
            break;
 
199
 
 
200
        case FILPBIT_SNAME :
 
201
            memset(data, 0, sizeof(u_int16_t));
 
202
            data += sizeof( u_int16_t );
 
203
            break;
 
204
 
 
205
        case FILPBIT_FNUM :
 
206
            aint = 0;
 
207
#if AD_VERSION > AD_VERSION1
 
208
            /* look in AD v2 header */
 
209
            if (adp)
 
210
                memcpy(&aint, ad_entry(adp, ADEID_DID), sizeof(aint));
 
211
#endif /* AD_VERSION > AD_VERSION1 */
 
212
 
 
213
#ifdef CNID_DB
 
214
            aint = cnid_add(vol->v_db, st, dir->d_did, upath,
 
215
                            strlen(upath), aint);
 
216
            /* Throw errors if cnid_add fails. */
 
217
            if (aint == CNID_INVALID) {
 
218
                switch (errno) {
 
219
                case CNID_ERR_PARAM:
 
220
                    LOG(log_error, logtype_afpd, "getfilparams: Incorrect parameters passed to cnid_add");
 
221
                    return(AFPERR_PARAM);
 
222
                case CNID_ERR_PATH:
 
223
                    return(AFPERR_PARAM);
 
224
                case CNID_ERR_DB:
 
225
                case CNID_ERR_MAX:
 
226
                    return(AFPERR_MISC);
 
227
                }
 
228
            }
 
229
#endif /* CNID_DB */
 
230
 
 
231
            if (aint == 0) {
 
232
                /*
 
233
                 * What a fucking mess.  First thing:  DID and FNUMs are
 
234
                 * in the same space for purposes of enumerate (and several
 
235
                 * other wierd places).  While we consider this Apple's bug,
 
236
                 * this is the work-around:  In order to maintain constant and
 
237
                 * unique DIDs and FNUMs, we monotonically generate the DIDs
 
238
                 * during the session, and derive the FNUMs from the filesystem.
 
239
                 * Since the DIDs are small, we insure that the FNUMs are fairly
 
240
                 * large by setting thier high bits to the device number.
 
241
                 *
 
242
                 * AFS already does something very similar to this for the
 
243
                 * inode number, so we don't repeat the procedure.
 
244
                 *
 
245
                 * new algorithm:
 
246
                 * due to complaints over did's being non-persistent,
 
247
                 * here's the current hack to provide semi-persistent
 
248
                 * did's:
 
249
                 *      1) we reserve the first bit for file ids.
 
250
                 *      2) the next 7 bits are for the device.
 
251
                 *      3) the remaining 24 bits are for the inode.
 
252
                 *
 
253
                 * both the inode and device information are actually hashes
 
254
                 * that are then truncated to the requisite bit length.
 
255
                 *
 
256
                 * it should be okay to use lstat to deal with symlinks.
 
257
                 */
 
258
#ifdef USE_LASTDID
 
259
                aint = htonl(( st->st_dev << 16 ) | (st->st_ino & 0x0000ffff));
 
260
#else /* USE_LASTDID */
 
261
                lstp = lstat(upath, &lst) < 0 ? st : &lst;
 
262
                aint = htonl(CNID(lstp, 1));
 
263
#endif /* USE_LASTDID */
 
264
            }
 
265
 
 
266
            memcpy(data, &aint, sizeof( aint ));
 
267
            data += sizeof( aint );
 
268
            break;
 
269
 
 
270
        case FILPBIT_DFLEN :
 
271
            aint = htonl( st->st_size );
 
272
            memcpy(data, &aint, sizeof( aint ));
 
273
            data += sizeof( aint );
 
274
            break;
 
275
 
 
276
        case FILPBIT_RFLEN :
 
277
            if ( adp ) {
 
278
                aint = htonl( ad_getentrylen( adp, ADEID_RFORK ));
 
279
            } else {
 
280
                aint = 0;
 
281
            }
 
282
            memcpy(data, &aint, sizeof( aint ));
 
283
            data += sizeof( aint );
 
284
            break;
 
285
 
 
286
            /* Current client needs ProDOS info block for this file.
 
287
               Use simple heuristic and let the Mac "type" string tell
 
288
               us what the PD file code should be.  Everything gets a
 
289
               subtype of 0x0000 unless the original value was hashed
 
290
               to "pXYZ" when we created it.  See IA, Ver 2.
 
291
               <shirsch@ibm.net> */
 
292
        case FILPBIT_PDINFO :
 
293
            if ( adp ) {
 
294
                memcpy(fdType, ad_entry( adp, ADEID_FINDERI ), 4 );
 
295
 
 
296
                if ( memcmp( fdType, "TEXT", 4 ) == 0 ) {
 
297
                    achar = '\x04';
 
298
                    ashort = 0x0000;
 
299
                }
 
300
                else if ( memcmp( fdType, "PSYS", 4 ) == 0 ) {
 
301
                    achar = '\xff';
 
302
                    ashort = 0x0000;
 
303
                }
 
304
                else if ( memcmp( fdType, "PS16", 4 ) == 0 ) {
 
305
                    achar = '\xb3';
 
306
                    ashort = 0x0000;
 
307
                }
 
308
                else if ( memcmp( fdType, "BINA", 4 ) == 0 ) {
 
309
                    achar = '\x00';
 
310
                    ashort = 0x0000;
 
311
                }
 
312
                else if ( fdType[0] == 'p' ) {
 
313
                    achar = fdType[1];
 
314
                    ashort = (fdType[2] * 256) + fdType[3];
 
315
                }
 
316
                else {
 
317
                    achar = '\x00';
 
318
                    ashort = 0x0000;
 
319
                }
 
320
            }
 
321
            else {
 
322
                achar = '\x00';
 
323
                ashort = 0x0000;
 
324
            }
 
325
 
 
326
            *data++ = achar;
 
327
            *data++ = 0;
 
328
            memcpy(data, &ashort, sizeof( ashort ));
 
329
            data += sizeof( ashort );
 
330
            memset(data, 0, sizeof( ashort ));
 
331
            data += sizeof( ashort );
 
332
            break;
 
333
 
 
334
        default :
 
335
            return( AFPERR_BITMAP );
 
336
        }
 
337
        bitmap = bitmap>>1;
 
338
        bit++;
 
339
    }
 
340
    if ( nameoff ) {
 
341
        ashort = htons( data - buf );
 
342
        memcpy(nameoff, &ashort, sizeof( ashort ));
 
343
        if ((aint = strlen( path )) > MACFILELEN)
 
344
            aint = MACFILELEN;
 
345
        *data++ = aint;
 
346
        memcpy(data, path, aint );
 
347
        data += aint;
 
348
    }
 
349
    *buflen = data - buf;
 
350
    return (AFP_OK);
 
351
}
 
352
                
 
353
/* ----------------------- */
 
354
int getfilparams(struct vol *vol,
 
355
                 u_int16_t bitmap,
 
356
                 char *path, struct dir *dir, struct stat *st,
 
357
                 char *buf, int *buflen )
 
358
{
 
359
    struct adouble      ad, *adp;
 
360
    struct ofork        *of;
 
361
    char                    *upath;
 
362
    u_int16_t           attrbits = 0;
 
363
    int rc;    
 
364
#ifdef DEBUG
 
365
    LOG(log_info, logtype_afpd, "begin getfilparams:");
 
366
#endif /* DEBUG */
 
367
 
 
368
    upath = mtoupath(vol, path);
 
369
    if ((of = of_findname(upath, st))) {
 
370
        adp = of->of_ad;
 
371
        attrbits = ((of->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
 
372
        attrbits |= ((of->of_ad->ad_hf.adf_refcount > of->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
 
373
 
 
374
    } else {
 
375
        memset(&ad, 0, sizeof(ad));
 
376
        adp = &ad;
 
377
    }
 
378
 
 
379
    if ( ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, adp) < 0 ) {
 
380
        adp = NULL;
 
381
    }
 
382
    else {
 
383
#if 0
 
384
        /* FIXME 
 
385
           we need to check if the file is open by another process.
 
386
           it's slow so we only do it if we have to:
 
387
           - bitmap is requested.
 
388
           - we don't already have the answer!
 
389
        */
 
390
        if ((bitmap & (1 << FILPBIT_ATTR))) {
 
391
                if (!(attrbits & ATTRBIT_ROPEN)) {
 
392
                }
 
393
                if (!(attrbits & ATTRBIT_DOPEN)) {
 
394
                }
 
395
        }
 
396
#endif          
 
397
    }
 
398
    rc = getmetadata(vol, bitmap, path, dir, st, buf, buflen, adp, attrbits);
 
399
    if ( adp ) {
 
400
        ad_close( adp, ADFLAGS_HF );
 
401
    }
 
402
#ifdef DEBUG
 
403
    LOG(log_info, logtype_afpd, "end getfilparams:");
 
404
#endif /* DEBUG */
 
405
 
 
406
    return( rc );
 
407
}
 
408
 
 
409
/* ----------------------------- */
 
410
int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen )
 
411
AFPObj      *obj;
 
412
char    *ibuf, *rbuf;
 
413
int             ibuflen, *rbuflen;
 
414
{
 
415
    struct stat         st;
 
416
    struct adouble      ad, *adp;
 
417
    struct vol          *vol;
 
418
    struct dir          *dir;
 
419
    struct ofork        *of = NULL;
 
420
    char                *path, *upath;
 
421
    int                 creatf, did, openf, retvalue = AFP_OK;
 
422
    u_int16_t           vid;
 
423
    int                 ret;
 
424
#ifdef DEBUG
 
425
    LOG(log_info, logtype_afpd, "begin afp_createfile:");
 
426
#endif /* DEBUG */
 
427
 
 
428
    *rbuflen = 0;
 
429
    ibuf++;
 
430
    creatf = (unsigned char) *ibuf++;
 
431
 
 
432
    memcpy(&vid, ibuf, sizeof( vid ));
 
433
    ibuf += sizeof( vid );
 
434
 
 
435
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
436
        return( AFPERR_PARAM );
 
437
    }
 
438
 
 
439
    if (vol->v_flags & AFPVOL_RO)
 
440
        return AFPERR_VLOCK;
 
441
 
 
442
    memcpy(&did, ibuf, sizeof( did));
 
443
    ibuf += sizeof( did );
 
444
 
 
445
    if (( dir = dirlookup( vol, did )) == NULL ) {
 
446
        return( AFPERR_NOOBJ );
 
447
    }
 
448
 
 
449
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
450
        return( AFPERR_NOOBJ );
 
451
    }
 
452
 
 
453
    upath = mtoupath(vol, path);
 
454
    if (0 != (ret = check_name(vol, upath))) 
 
455
       return  ret;
 
456
 
 
457
    ret = stat(upath, &st);
 
458
    /* if upath is deleted we already in trouble anyway */
 
459
    if (!ret && (of = of_findname(upath, &st))) {
 
460
        adp = of->of_ad;
 
461
    } else {
 
462
        memset(&ad, 0, sizeof(ad));
 
463
        adp = &ad;
 
464
    }
 
465
    if ( creatf) {
 
466
        /* on a hard create, fail if file exists and is open */
 
467
        if (!ret && of)
 
468
            return AFPERR_BUSY;
 
469
        openf = O_RDWR|O_CREAT|O_TRUNC;
 
470
    } else {
 
471
        /* on a soft create, if the file is open then ad_open won't fail
 
472
           because open syscall is not called
 
473
        */
 
474
        if (of) {
 
475
                return AFPERR_EXIST;
 
476
        }
 
477
        openf = O_RDWR|O_CREAT|O_EXCL;
 
478
    }
 
479
 
 
480
    if ( ad_open( upath, vol_noadouble(vol)|ADFLAGS_DF|ADFLAGS_HF,
 
481
                  openf, 0666, adp) < 0 ) {
 
482
        switch ( errno ) {
 
483
        case EEXIST :
 
484
            return( AFPERR_EXIST );
 
485
        case EACCES :
 
486
            return( AFPERR_ACCESS );
 
487
        case ENOENT:
 
488
            /* on noadouble volumes, just creating the data fork is ok */
 
489
            if (vol_noadouble(vol) && (stat(upath, &st) == 0))
 
490
                goto createfile_done;
 
491
            /* fallthrough */
 
492
        default :
 
493
            return( AFPERR_PARAM );
 
494
        }
 
495
    }
 
496
 
 
497
    ad_setentrylen( adp, ADEID_NAME, strlen( path ));
 
498
    memcpy(ad_entry( adp, ADEID_NAME ), path,
 
499
           ad_getentrylen( adp, ADEID_NAME ));
 
500
    ad_flush( adp, ADFLAGS_DF|ADFLAGS_HF );
 
501
    ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
 
502
 
 
503
createfile_done:
 
504
 
 
505
#ifdef DROPKLUDGE
 
506
    if (vol->v_flags & AFPVOL_DROPBOX) {
 
507
        retvalue = matchfile2dirperms(upath, vol, did);
 
508
    }
 
509
#endif /* DROPKLUDGE */
 
510
 
 
511
    setvoltime(obj, vol );
 
512
 
 
513
#ifdef DEBUG
 
514
    LOG(log_info, logtype_afpd, "end afp_createfile");
 
515
#endif /* DEBUG */
 
516
 
 
517
    return (retvalue);
 
518
}
 
519
 
 
520
int afp_setfilparams(obj, ibuf, ibuflen, rbuf, rbuflen )
 
521
AFPObj      *obj;
 
522
char    *ibuf, *rbuf;
 
523
int             ibuflen, *rbuflen;
 
524
{
 
525
    struct vol  *vol;
 
526
    struct dir  *dir;
 
527
    char        *path;
 
528
    int         did, rc;
 
529
    u_int16_t   vid, bitmap;
 
530
 
 
531
#ifdef DEBUG
 
532
    LOG(log_info, logtype_afpd, "begin afp_setfilparams:");
 
533
#endif /* DEBUG */
 
534
 
 
535
    *rbuflen = 0;
 
536
    ibuf += 2;
 
537
 
 
538
    memcpy(&vid, ibuf, sizeof( vid ));
 
539
    ibuf += sizeof( vid );
 
540
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
541
        return( AFPERR_PARAM );
 
542
    }
 
543
 
 
544
    if (vol->v_flags & AFPVOL_RO)
 
545
        return AFPERR_VLOCK;
 
546
 
 
547
    memcpy(&did, ibuf, sizeof( did ));
 
548
    ibuf += sizeof( did );
 
549
    if (( dir = dirlookup( vol, did )) == NULL ) {
 
550
        return( AFPERR_NOOBJ );
 
551
    }
 
552
 
 
553
    memcpy(&bitmap, ibuf, sizeof( bitmap ));
 
554
    bitmap = ntohs( bitmap );
 
555
    ibuf += sizeof( bitmap );
 
556
 
 
557
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
558
        return( AFPERR_NOOBJ );
 
559
    }
 
560
 
 
561
    if ( *path == '\0' ) {
 
562
        return( AFPERR_BADTYPE ); /* it's a directory */
 
563
    }
 
564
 
 
565
    if ((u_long)ibuf & 1 ) {
 
566
        ibuf++;
 
567
    }
 
568
 
 
569
    if (( rc = setfilparams(vol, path, bitmap, ibuf )) == AFP_OK ) {
 
570
        setvoltime(obj, vol );
 
571
    }
 
572
 
 
573
#ifdef DEBUG
 
574
    LOG(log_info, logtype_afpd, "end afp_setfilparams:");
 
575
#endif /* DEBUG */
 
576
 
 
577
    return( rc );
 
578
}
 
579
 
 
580
/*
 
581
 * cf AFP3.0.pdf page 252 for change_mdate and change_parent_mdate logic  
 
582
 *
 
583
*/
 
584
 
 
585
int setfilparams(struct vol *vol,
 
586
                 char *path, u_int16_t bitmap, char *buf )
 
587
{
 
588
    struct adouble      ad, *adp;
 
589
    struct ofork        *of;
 
590
    struct extmap       *em;
 
591
    int                 bit = 0, isad = 1, err = AFP_OK;
 
592
    char                *upath;
 
593
    u_char              achar, *fdType, xyy[4];
 
594
    u_int16_t           ashort, bshort;
 
595
    u_int32_t           aint;
 
596
    struct utimbuf      ut;
 
597
 
 
598
    int                 change_mdate = 0;
 
599
    int                 change_parent_mdate = 0;
 
600
    int                 newdate = 0;
 
601
    struct timeval      tv;
 
602
 
 
603
 
 
604
#ifdef DEBUG
 
605
    LOG(log_info, logtype_afpd, "begin setfilparams:");
 
606
#endif /* DEBUG */
 
607
 
 
608
    upath = mtoupath(vol, path);
 
609
    if ((of = of_findname(upath, NULL))) {
 
610
        adp = of->of_ad;
 
611
    } else {
 
612
        memset(&ad, 0, sizeof(ad));
 
613
        adp = &ad;
 
614
    }
 
615
 
 
616
    if (check_access(upath, OPENACC_WR ) < 0) {
 
617
        return AFPERR_ACCESS;
 
618
    }
 
619
 
 
620
    if (ad_open( upath, vol_noadouble(vol) | ADFLAGS_HF,
 
621
                 O_RDWR|O_CREAT, 0666, adp) < 0) {
 
622
        /* for some things, we don't need an adouble header */
 
623
        if (bitmap & ~(1<<FILPBIT_MDATE)) {
 
624
            return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
 
625
        }
 
626
        isad = 0;
 
627
    } else if ((ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
 
628
        ad_setentrylen( adp, ADEID_NAME, strlen( path ));
 
629
        memcpy(ad_entry( adp, ADEID_NAME ), path,
 
630
               ad_getentrylen( adp, ADEID_NAME ));
 
631
    }
 
632
 
 
633
    while ( bitmap != 0 ) {
 
634
        while (( bitmap & 1 ) == 0 ) {
 
635
            bitmap = bitmap>>1;
 
636
            bit++;
 
637
        }
 
638
 
 
639
        switch(  bit ) {
 
640
        case FILPBIT_ATTR :
 
641
            change_mdate = 1;
 
642
            memcpy(&ashort, buf, sizeof( ashort ));
 
643
            ad_getattr(adp, &bshort);
 
644
            if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
 
645
                bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
 
646
            } else {
 
647
                bshort &= ~ashort;
 
648
            }
 
649
            if ((ashort & htons(ATTRBIT_INVISIBLE)))
 
650
                change_parent_mdate = 1;
 
651
            ad_setattr(adp, bshort);
 
652
            buf += sizeof( ashort );
 
653
            break;
 
654
 
 
655
        case FILPBIT_CDATE :
 
656
            change_mdate = 1;
 
657
            memcpy(&aint, buf, sizeof(aint));
 
658
            ad_setdate(adp, AD_DATE_CREATE, aint);
 
659
            buf += sizeof( aint );
 
660
            break;
 
661
 
 
662
        case FILPBIT_MDATE :
 
663
            memcpy(&newdate, buf, sizeof( newdate ));
 
664
            buf += sizeof( newdate );
 
665
            break;
 
666
 
 
667
        case FILPBIT_BDATE :
 
668
            change_mdate = 1;
 
669
            memcpy(&aint, buf, sizeof(aint));
 
670
            ad_setdate(adp, AD_DATE_BACKUP, aint);
 
671
            buf += sizeof( aint );
 
672
            break;
 
673
 
 
674
        case FILPBIT_FINFO :
 
675
            change_mdate = 1;
 
676
 
 
677
            if (!memcmp( ad_entry( adp, ADEID_FINDERI ), ufinderi, 8 )
 
678
                    && ( 
 
679
                     ((em = getextmap( path )) &&
 
680
                      !memcmp(buf, em->em_type, sizeof( em->em_type )) &&
 
681
                      !memcmp(buf + 4, em->em_creator,sizeof( em->em_creator)))
 
682
                     || ((em = getdefextmap()) &&
 
683
                      !memcmp(buf, em->em_type, sizeof( em->em_type )) &&
 
684
                      !memcmp(buf + 4, em->em_creator,sizeof( em->em_creator)))
 
685
            )) {
 
686
                memcpy(buf, ufinderi, 8 );
 
687
            }
 
688
 
 
689
            memcpy(ad_entry( adp, ADEID_FINDERI ), buf, 32 );
 
690
            buf += 32;
 
691
            break;
 
692
 
 
693
            /* Client needs to set the ProDOS file info for this file.
 
694
               Use defined strings for the simple cases, and convert
 
695
               all else into pXYY per Inside Appletalk.  Always set
 
696
               the creator as "pdos". <shirsch@ibm.net> */
 
697
        case FILPBIT_PDINFO :
 
698
            achar = *buf;
 
699
            buf += 2;
 
700
            memcpy(&ashort, buf, sizeof( ashort ));
 
701
            ashort = ntohs( ashort );
 
702
            buf += 2;
 
703
 
 
704
            switch ( (unsigned int) achar )
 
705
            {
 
706
            case 0x04 :
 
707
                fdType = ( u_char *) "TEXT";
 
708
                break;
 
709
 
 
710
            case 0xff :
 
711
                fdType = ( u_char *) "PSYS";
 
712
                break;
 
713
 
 
714
            case 0xb3 :
 
715
                fdType = ( u_char *) "PS16";
 
716
                break;
 
717
 
 
718
            case 0x00 :
 
719
                fdType = ( u_char *) "BINA";
 
720
                break;
 
721
 
 
722
            default :
 
723
                xyy[0] = ( u_char ) 'p';
 
724
                xyy[1] = achar;
 
725
                xyy[2] = ( u_char ) ( ashort >> 8 ) & 0xff;
 
726
                xyy[3] = ( u_char ) ashort & 0xff;
 
727
                fdType = xyy;
 
728
                break;
 
729
            }
 
730
 
 
731
            memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 );
 
732
            memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 );
 
733
            break;
 
734
 
 
735
 
 
736
        default :
 
737
            err = AFPERR_BITMAP;
 
738
            goto setfilparam_done;
 
739
        }
 
740
 
 
741
        bitmap = bitmap>>1;
 
742
        bit++;
 
743
    }
 
744
 
 
745
setfilparam_done:
 
746
    if (change_mdate && newdate == 0 && gettimeofday(&tv, NULL) == 0) {
 
747
       newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
 
748
    }
 
749
    if (newdate) {
 
750
       if (isad)
 
751
          ad_setdate(adp, AD_DATE_MODIFY, newdate);
 
752
       ut.actime = ut.modtime = AD_DATE_TO_UNIX(newdate);
 
753
       utime(upath, &ut);
 
754
    }
 
755
 
 
756
    if (isad) {
 
757
        ad_flush( adp, ADFLAGS_HF );
 
758
        ad_close( adp, ADFLAGS_HF );
 
759
 
 
760
    }
 
761
 
 
762
    if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
 
763
        newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
 
764
        bitmap = 1<<FILPBIT_MDATE;
 
765
        setdirparams(vol, "", bitmap, (char *)&newdate);
 
766
    }
 
767
 
 
768
#ifdef DEBUG
 
769
    LOG(log_info, logtype_afpd, "end setfilparams:");
 
770
#endif /* DEBUG */
 
771
    return err;
 
772
}
 
773
 
 
774
/*
 
775
 * renamefile and copyfile take the old and new unix pathnames
 
776
 * and the new mac name.
 
777
 * NOTE: if we have to copy a file instead of renaming it, locks
 
778
 *       will break. Anyway it's an error because then we have 2 files.
 
779
 *
 
780
 * src         the source path 
 
781
 * dst         the dest filename in current dir
 
782
 * newname     the dest mac name
 
783
 * adp         adouble struct of src file, if open, or & zeroed one
 
784
 *
 
785
 */
 
786
int renamefile(src, dst, newname, noadouble, adp )
 
787
char    *src, *dst, *newname;
 
788
const int         noadouble;
 
789
struct adouble    *adp;
 
790
{
 
791
    char                adsrc[ MAXPATHLEN + 1];
 
792
    int                 len, rc;
 
793
 
 
794
    /*
 
795
     * Note that this is only checking the existance of the data file,
 
796
     * not the header file.  The thinking is that if the data file doesn't
 
797
     * exist, but the header file does, the right thing to do is remove
 
798
     * the data file silently.
 
799
     */
 
800
 
 
801
    /* existence check moved to afp_moveandrename */
 
802
 
 
803
#ifdef DEBUG
 
804
    LOG(log_info, logtype_afpd, "begin renamefile:");
 
805
#endif /* DEBUG */
 
806
 
 
807
    if ( rename( src, dst ) < 0 ) {
 
808
        switch ( errno ) {
 
809
        case ENOENT :
 
810
            return( AFPERR_NOOBJ );
 
811
        case EPERM:
 
812
        case EACCES :
 
813
            return( AFPERR_ACCESS );
 
814
        case EROFS:
 
815
            return AFPERR_VLOCK;
 
816
        case EXDEV :                    /* Cross device move -- try copy */
 
817
            if (( rc = copyfile(src, dst, newname, noadouble )) != AFP_OK ) {
 
818
                deletefile( dst, 0 );
 
819
                return( rc );
 
820
            }
 
821
            return deletefile( src, 0);
 
822
        default :
 
823
            return( AFPERR_PARAM );
 
824
        }
 
825
    }
 
826
 
 
827
    strcpy( adsrc, ad_path( src, 0 ));
 
828
    rc = 0;
 
829
rename_retry:
 
830
    if (rename( adsrc, ad_path( dst, 0 )) < 0 ) {
 
831
        struct stat st;
 
832
 
 
833
        switch ( errno ) {
 
834
        case ENOENT :
 
835
            /* check for a source appledouble header. if it exists, make
 
836
             * a dest appledouble directory and do the rename again. */
 
837
            if (rc || stat(adsrc, &st) ||
 
838
                    (ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, adp) < 0))
 
839
                return AFP_OK;
 
840
            rc++;
 
841
            ad_close(adp, ADFLAGS_HF);
 
842
            goto rename_retry;
 
843
        case EPERM:
 
844
        case EACCES :
 
845
            return( AFPERR_ACCESS );
 
846
        case EROFS:
 
847
            return AFPERR_VLOCK;
 
848
        default :
 
849
            return( AFPERR_PARAM );
 
850
        }
 
851
    }
 
852
 
 
853
    if ( ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp) < 0 ) {
 
854
        switch ( errno ) {
 
855
        case ENOENT :
 
856
            return( AFPERR_NOOBJ );
 
857
        case EACCES :
 
858
            return( AFPERR_ACCESS );
 
859
        case EROFS:
 
860
            return AFPERR_VLOCK;
 
861
        default :
 
862
            return( AFPERR_PARAM );
 
863
        }
 
864
    }
 
865
 
 
866
    len = strlen( newname );
 
867
    ad_setentrylen( adp, ADEID_NAME, len );
 
868
    memcpy(ad_entry( adp, ADEID_NAME ), newname, len );
 
869
    ad_flush( adp, ADFLAGS_HF );
 
870
    ad_close( adp, ADFLAGS_HF );
 
871
 
 
872
#ifdef DEBUG
 
873
    LOG(log_info, logtype_afpd, "end renamefile:");
 
874
#endif /* DEBUG */
 
875
 
 
876
    return( AFP_OK );
 
877
}
 
878
 
 
879
int afp_copyfile(obj, ibuf, ibuflen, rbuf, rbuflen )
 
880
AFPObj      *obj;
 
881
char    *ibuf, *rbuf;
 
882
int             ibuflen, *rbuflen;
 
883
{
 
884
    struct vol  *vol;
 
885
    struct dir  *dir;
 
886
    char        *newname, *path, *p, *upath;
 
887
    u_int32_t   sdid, ddid;
 
888
    int         plen, err, retvalue = AFP_OK;
 
889
    u_int16_t   svid, dvid;
 
890
 
 
891
#ifdef DEBUG
 
892
    LOG(log_info, logtype_afpd, "begin afp_copyfile:");
 
893
#endif /* DEBUG */
 
894
 
 
895
    *rbuflen = 0;
 
896
    ibuf += 2;
 
897
 
 
898
    memcpy(&svid, ibuf, sizeof( svid ));
 
899
    ibuf += sizeof( svid );
 
900
    if (( vol = getvolbyvid( svid )) == NULL ) {
 
901
        return( AFPERR_PARAM );
 
902
    }
 
903
 
 
904
    memcpy(&sdid, ibuf, sizeof( sdid ));
 
905
    ibuf += sizeof( sdid );
 
906
    if (( dir = dirlookup( vol, sdid )) == NULL ) {
 
907
        return( AFPERR_PARAM );
 
908
    }
 
909
 
 
910
    memcpy(&dvid, ibuf, sizeof( dvid ));
 
911
    ibuf += sizeof( dvid );
 
912
    memcpy(&ddid, ibuf, sizeof( ddid ));
 
913
    ibuf += sizeof( ddid );
 
914
 
 
915
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
916
        return( AFPERR_NOOBJ );
 
917
    }
 
918
    if ( *path == '\0' ) {
 
919
        return( AFPERR_BADTYPE );
 
920
    }
 
921
 
 
922
    /* don't allow copies when the file is open.
 
923
     * XXX: the spec only calls for read/deny write access.
 
924
     *      however, copyfile doesn't have any of that info,
 
925
     *      and locks need to stay coherent. as a result,
 
926
     *      we just balk if the file is opened already. */
 
927
 
 
928
    newname = obj->newtmp;
 
929
    strcpy( newname, path );
 
930
 
 
931
    upath = mtoupath(vol, newname );
 
932
    if (of_findname(upath, NULL))
 
933
        return AFPERR_DENYCONF;
 
934
 
 
935
    p = ctoupath( vol, curdir, newname );
 
936
#ifdef FORCE_UIDGID
 
937
    /* FIXME svid != dvid && dvid's user can't read svid */
 
938
#endif
 
939
    if (( vol = getvolbyvid( dvid )) == NULL ) {
 
940
        return( AFPERR_PARAM );
 
941
    }
 
942
 
 
943
    if (vol->v_flags & AFPVOL_RO)
 
944
        return AFPERR_VLOCK;
 
945
 
 
946
    if (( dir = dirlookup( vol, ddid )) == NULL ) {
 
947
        return( AFPERR_PARAM );
 
948
    }
 
949
 
 
950
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
951
        return( AFPERR_NOOBJ );
 
952
    }
 
953
    if ( *path != '\0' ) {
 
954
        return( AFPERR_BADTYPE ); /* not a directory. AFPERR_PARAM? */
 
955
    }
 
956
 
 
957
    /* one of the handful of places that knows about the path type */
 
958
    if ( *ibuf++ != 2 ) {
 
959
        return( AFPERR_PARAM );
 
960
    }
 
961
    if (( plen = (unsigned char)*ibuf++ ) != 0 ) {
 
962
        strncpy( newname, ibuf, plen );
 
963
        newname[ plen ] = '\0';
 
964
        if (strlen(newname) != plen) {
 
965
            /* there's \0 in newname, e.g. it's a pathname not
 
966
             * only a filename. 
 
967
            */
 
968
            return( AFPERR_PARAM );
 
969
        }
 
970
    }
 
971
    upath = mtoupath(vol, newname);
 
972
    if ( (err = copyfile(p, upath , newname, vol_noadouble(vol))) < 0 ) {
 
973
        return err;
 
974
    }
 
975
 
 
976
#ifdef DROPKLUDGE
 
977
    if (vol->v_flags & AFPVOL_DROPBOX) {
 
978
        retvalue=matchfile2dirperms(upath, vol, ddid); /* FIXME sdir or ddid */
 
979
    }
 
980
#endif /* DROPKLUDGE */
 
981
 
 
982
    setvoltime(obj, vol );
 
983
 
 
984
#ifdef DEBUG
 
985
    LOG(log_info, logtype_afpd, "end afp_copyfile:");
 
986
#endif /* DEBUG */
 
987
 
 
988
    return( retvalue );
 
989
}
 
990
 
 
991
 
 
992
static __inline__ int copy_all(const int dfd, const void *buf,
 
993
                               size_t buflen)
 
994
{
 
995
    ssize_t cc;
 
996
 
 
997
#ifdef DEBUG
 
998
    LOG(log_info, logtype_afpd, "begin copy_all:");
 
999
#endif /* DEBUG */
 
1000
 
 
1001
    while (buflen > 0) {
 
1002
        if ((cc = write(dfd, buf, buflen)) < 0) {
 
1003
            switch (errno) {
 
1004
            case EINTR:
 
1005
                continue;
 
1006
            case EDQUOT:
 
1007
            case EFBIG:
 
1008
            case ENOSPC:
 
1009
                return AFPERR_DFULL;
 
1010
            case EROFS:
 
1011
                return AFPERR_VLOCK;
 
1012
            default:
 
1013
                return AFPERR_PARAM;
 
1014
            }
 
1015
        }
 
1016
        buflen -= cc;
 
1017
    }
 
1018
 
 
1019
#ifdef DEBUG
 
1020
    LOG(log_info, logtype_afpd, "end copy_all:");
 
1021
#endif /* DEBUG */
 
1022
 
 
1023
    return AFP_OK;
 
1024
}
 
1025
 
 
1026
/* XXX: this needs to use ad_open and ad_lock. so, we need to
 
1027
 * pass in vol and path */
 
1028
int copyfile(src, dst, newname, noadouble )
 
1029
char    *src, *dst, *newname;
 
1030
const int   noadouble;
 
1031
{
 
1032
    struct adouble      ad;
 
1033
    struct stat         st;
 
1034
    char                filebuf[8192];
 
1035
    int                 sfd, dfd, len, err = AFP_OK;
 
1036
    ssize_t             cc;
 
1037
    char                dpath[ MAXPATHLEN + 1];
 
1038
    int                 admode;
 
1039
#ifdef DEBUG
 
1040
    LOG(log_info, logtype_afpd, "begin copyfile:");
 
1041
#endif /* DEBUG */
 
1042
 
 
1043
    strcpy(dpath, ad_path( dst, ADFLAGS_HF ));
 
1044
    admode = ad_mode( dst, 0666 );
 
1045
    if (newname) {
 
1046
        if ((sfd = open( ad_path( src, ADFLAGS_HF ), O_RDONLY, 0 )) < 0 ) {
 
1047
            switch ( errno ) {
 
1048
            case ENOENT :
 
1049
                break; /* just copy the data fork */
 
1050
            case EACCES :
 
1051
                return( AFPERR_ACCESS );
 
1052
            default :
 
1053
                return( AFPERR_PARAM );
 
1054
            }
 
1055
        } else {
 
1056
            if (( dfd = open( dpath, O_WRONLY|O_CREAT,ad_hf_mode(admode))) < 0 ) {
 
1057
                close( sfd );
 
1058
                switch ( errno ) {
 
1059
                case ENOENT :
 
1060
                    return( AFPERR_NOOBJ );
 
1061
                case EACCES :
 
1062
                    return( AFPERR_ACCESS );
 
1063
                case EROFS:
 
1064
                    return AFPERR_VLOCK;
 
1065
                default :
 
1066
                    return( AFPERR_PARAM );
 
1067
                }
 
1068
            }
 
1069
 
 
1070
            /* copy the file */
 
1071
#ifdef SENDFILE_FLAVOR_LINUX
 
1072
            if (fstat(sfd, &st) == 0) {
 
1073
                if ((cc = sendfile(dfd, sfd, NULL, st.st_size)) < 0) {
 
1074
                    switch (errno) {
 
1075
                    case EDQUOT:
 
1076
                    case EFBIG:
 
1077
                    case ENOSPC:
 
1078
                        err = AFPERR_DFULL;
 
1079
                        break;
 
1080
                    case EROFS:
 
1081
                        err = AFPERR_VLOCK;
 
1082
                        break;
 
1083
                    default:
 
1084
                        err = AFPERR_PARAM;
 
1085
                    }
 
1086
                }
 
1087
                goto copyheader_done;
 
1088
            }
 
1089
#endif /* SENDFILE_FLAVOR_LINUX */
 
1090
            while (1) {
 
1091
                if ((cc = read(sfd, filebuf, sizeof(filebuf))) < 0) {
 
1092
                    if (errno == EINTR)
 
1093
                        continue;
 
1094
                    err = AFPERR_PARAM;
 
1095
                    break;
 
1096
                }
 
1097
 
 
1098
                if (!cc || ((err = copy_all(dfd, filebuf, cc)) < 0))
 
1099
                    break;
 
1100
            }
 
1101
 
 
1102
copyheader_done:
 
1103
            close(sfd);
 
1104
            close(dfd);
 
1105
            if (err < 0) {
 
1106
                unlink(dpath);
 
1107
                return err;
 
1108
            }
 
1109
        }
 
1110
    }
 
1111
 
 
1112
    /* data fork copying */
 
1113
    if (( sfd = open( src, O_RDONLY, 0 )) < 0 ) {
 
1114
        switch ( errno ) {
 
1115
        case ENOENT :
 
1116
            return( AFPERR_NOOBJ );
 
1117
        case EACCES :
 
1118
            return( AFPERR_ACCESS );
 
1119
        default :
 
1120
            return( AFPERR_PARAM );
 
1121
        }
 
1122
    }
 
1123
 
 
1124
    if (( dfd = open( dst, O_WRONLY|O_CREAT, admode)) < 0 ) {
 
1125
        close( sfd );
 
1126
        switch ( errno ) {
 
1127
        case ENOENT :
 
1128
            return( AFPERR_NOOBJ );
 
1129
        case EACCES :
 
1130
            return( AFPERR_ACCESS );
 
1131
        case EROFS:
 
1132
            return AFPERR_VLOCK;
 
1133
        default :
 
1134
            return( AFPERR_PARAM );
 
1135
        }
 
1136
    }
 
1137
 
 
1138
#ifdef SENDFILE_FLAVOR_LINUX
 
1139
    if (fstat(sfd, &st) == 0) {
 
1140
        if ((cc = sendfile(dfd, sfd, NULL, st.st_size)) < 0) {
 
1141
            switch (errno) {
 
1142
            case EDQUOT:
 
1143
            case EFBIG:
 
1144
            case ENOSPC:
 
1145
                err = AFPERR_DFULL;
 
1146
                break;
 
1147
            default:
 
1148
                err = AFPERR_PARAM;
 
1149
            }
 
1150
        }
 
1151
        goto copydata_done;
 
1152
    }
 
1153
#endif /* SENDFILE_FLAVOR_LINUX */
 
1154
 
 
1155
    while (1) {
 
1156
        if ((cc = read( sfd, filebuf, sizeof( filebuf ))) < 0) {
 
1157
            if (errno == EINTR)
 
1158
                continue;
 
1159
 
 
1160
            err = AFPERR_PARAM;
 
1161
            break;
 
1162
        }
 
1163
 
 
1164
        if (!cc || ((err = copy_all(dfd, filebuf, cc)) < 0)) {
 
1165
            break;
 
1166
        }
 
1167
    }
 
1168
 
 
1169
copydata_done:
 
1170
    close(sfd);
 
1171
    close(dfd);
 
1172
    if (err < 0) {
 
1173
        unlink(dpath);
 
1174
        unlink(dst);
 
1175
        return err;
 
1176
    }
 
1177
 
 
1178
    if (newname) {
 
1179
        memset(&ad, 0, sizeof(ad));
 
1180
        if ( ad_open( dst, noadouble | ADFLAGS_HF, O_RDWR|O_CREAT,
 
1181
                      0666, &ad) < 0 ) {
 
1182
            switch ( errno ) {
 
1183
            case ENOENT :
 
1184
                return noadouble ? AFP_OK : AFPERR_NOOBJ;
 
1185
            case EACCES :
 
1186
                return( AFPERR_ACCESS );
 
1187
            case EROFS:
 
1188
                return AFPERR_VLOCK;
 
1189
            default :
 
1190
                return( AFPERR_PARAM );
 
1191
            }
 
1192
        }
 
1193
 
 
1194
        len = strlen( newname );
 
1195
        ad_setentrylen( &ad, ADEID_NAME, len );
 
1196
        memcpy(ad_entry( &ad, ADEID_NAME ), newname, len );
 
1197
        ad_flush( &ad, ADFLAGS_HF );
 
1198
        ad_close( &ad, ADFLAGS_HF );
 
1199
    }
 
1200
 
 
1201
#ifdef DEBUG
 
1202
    LOG(log_info, logtype_afpd, "end copyfile:");
 
1203
#endif /* DEBUG */
 
1204
 
 
1205
    return( AFP_OK );
 
1206
}
 
1207
 
 
1208
 
 
1209
/* -----------------------------------
 
1210
   checkAttrib:   1 check kFPDeleteInhibitBit 
 
1211
   ie deletfile called by afp_delete
 
1212
 
 
1213
   when deletefile is called we don't have lock on it, file is closed (for us)
 
1214
   untrue if called by renamefile
 
1215
*/
 
1216
int deletefile( file, checkAttrib )
 
1217
char            *file;
 
1218
int         checkAttrib;
 
1219
{
 
1220
    struct adouble      ad;
 
1221
    int                 adflags, err = AFP_OK;
 
1222
    int                 locktype = ADLOCK_WR;
 
1223
    int                 openmode = O_RDWR;
 
1224
 
 
1225
#ifdef DEBUG
 
1226
    LOG(log_info, logtype_afpd, "begin deletefile:");
 
1227
#endif /* DEBUG */
 
1228
 
 
1229
    while(1) {
 
1230
        /*
 
1231
         * If can't open read/write then try again read-only.  If it's open
 
1232
         * read-only, we must do a read lock instead of a write lock.
 
1233
         */
 
1234
        /* try to open both at once */
 
1235
        adflags = ADFLAGS_DF|ADFLAGS_HF;
 
1236
        memset(&ad, 0, sizeof(ad));
 
1237
        if ( ad_open( file, adflags, openmode, 0, &ad ) < 0 ) {
 
1238
            switch (errno) {
 
1239
            case ENOENT:
 
1240
                adflags = ADFLAGS_DF;
 
1241
                /* that failed. now try to open just the data fork */
 
1242
                memset(&ad, 0, sizeof(ad));
 
1243
                if ( ad_open( file, adflags, openmode, 0, &ad ) < 0 ) {
 
1244
                    switch (errno) {
 
1245
                    case ENOENT:
 
1246
                        return AFPERR_NOOBJ;
 
1247
                    case EACCES:
 
1248
                        if(openmode == O_RDWR) {
 
1249
                            openmode = O_RDONLY;
 
1250
                            locktype = ADLOCK_RD;
 
1251
                            continue;
 
1252
                        } else {
 
1253
                            return AFPERR_ACCESS;
 
1254
                        }
 
1255
                    case EROFS:
 
1256
                        return AFPERR_VLOCK;
 
1257
                    default:
 
1258
                        return AFPERR_PARAM;
 
1259
                    }
 
1260
                }
 
1261
                break;
 
1262
 
 
1263
            case EACCES:
 
1264
                if(openmode == O_RDWR) {
 
1265
                    openmode = O_RDONLY;
 
1266
                    locktype = ADLOCK_RD;
 
1267
                    continue;
 
1268
                } else {
 
1269
                    return AFPERR_ACCESS;
 
1270
                }
 
1271
            case EROFS:
 
1272
                return AFPERR_VLOCK;
 
1273
            default:
 
1274
                return( AFPERR_PARAM );
 
1275
            }
 
1276
        }
 
1277
        break;  /* from the while */
 
1278
    }
 
1279
    /*
 
1280
     * Does kFPDeleteInhibitBit (bit 8) set?
 
1281
     */
 
1282
    if (checkAttrib && (adflags & ADFLAGS_HF)) {
 
1283
        u_int16_t   bshort;
 
1284
 
 
1285
        ad_getattr(&ad, &bshort);
 
1286
        if ((bshort & htons(ATTRBIT_NODELETE))) {
 
1287
            ad_close( &ad, adflags );
 
1288
            return(AFPERR_OLOCK);
 
1289
        }
 
1290
    }
 
1291
    
 
1292
    if ((adflags & ADFLAGS_HF) ) {
 
1293
        /* FIXME we have a pb here because we want to know if a file is open 
 
1294
         * there's a 'priority inversion' if you can't open the ressource fork RW
 
1295
         * you can delete it if it's open because you can't get a write lock.
 
1296
         * 
 
1297
         * ADLOCK_FILELOCK means the whole ressource fork, not only after the 
 
1298
         * metadatas
 
1299
         *
 
1300
         * FIXME it doesn't for RFORK open read only and fork open without deny mode
 
1301
         */
 
1302
        if (ad_tmplock(&ad, ADEID_RFORK, locktype |ADLOCK_FILELOCK, 0, 0) < 0 ) {
 
1303
            ad_close( &ad, adflags );
 
1304
            return( AFPERR_BUSY );
 
1305
        }
 
1306
    }
 
1307
 
 
1308
    if (ad_tmplock( &ad, ADEID_DFORK, locktype, 0, 0 ) < 0) {
 
1309
        err = AFPERR_BUSY;
 
1310
        goto delete_unlock;
 
1311
    }
 
1312
 
 
1313
    if ( unlink( ad_path( file, ADFLAGS_HF )) < 0 ) {
 
1314
        switch ( errno ) {
 
1315
        case EPERM:
 
1316
        case EACCES :
 
1317
            err = AFPERR_ACCESS;
 
1318
            goto delete_unlock;
 
1319
        case EROFS:
 
1320
            err = AFPERR_VLOCK;
 
1321
            goto delete_unlock;
 
1322
        case ENOENT :
 
1323
            break;
 
1324
        default :
 
1325
            err = AFPERR_PARAM;
 
1326
            goto delete_unlock;
 
1327
        }
 
1328
    }
 
1329
 
 
1330
    if ( unlink( file ) < 0 ) {
 
1331
        switch ( errno ) {
 
1332
        case EPERM:
 
1333
        case EACCES :
 
1334
            err = AFPERR_ACCESS;
 
1335
            break;
 
1336
        case EROFS:
 
1337
            err = AFPERR_VLOCK;
 
1338
            break;
 
1339
        case ENOENT :
 
1340
            break;
 
1341
        default :
 
1342
            err = AFPERR_PARAM;
 
1343
            break;
 
1344
        }
 
1345
    }
 
1346
 
 
1347
delete_unlock:
 
1348
    if (adflags & ADFLAGS_HF)
 
1349
        ad_tmplock(&ad, ADEID_RFORK, ADLOCK_CLR |ADLOCK_FILELOCK, 0, 0);
 
1350
    ad_tmplock(&ad, ADEID_DFORK, ADLOCK_CLR, 0, 0);
 
1351
    ad_close( &ad, adflags );
 
1352
 
 
1353
#ifdef DEBUG
 
1354
    LOG(log_info, logtype_afpd, "end deletefile:");
 
1355
#endif /* DEBUG */
 
1356
 
 
1357
    return err;
 
1358
}
 
1359
 
 
1360
 
 
1361
#ifdef CNID_DB
 
1362
/* return a file id */
 
1363
int afp_createid(obj, ibuf, ibuflen, rbuf, rbuflen )
 
1364
AFPObj      *obj;
 
1365
char    *ibuf, *rbuf;
 
1366
int             ibuflen, *rbuflen;
 
1367
{
 
1368
    struct stat         st;
 
1369
#if AD_VERSION > AD_VERSION1
 
1370
    struct adouble      ad;
 
1371
#endif
 
1372
    struct vol          *vol;
 
1373
    struct dir          *dir;
 
1374
    char                *path, *upath;
 
1375
    int                 len;
 
1376
    cnid_t              did, id;
 
1377
    u_short             vid;
 
1378
 
 
1379
#ifdef DEBUG
 
1380
    LOG(log_info, logtype_afpd, "begin afp_createid:");
 
1381
#endif /* DEBUG */
 
1382
 
 
1383
    *rbuflen = 0;
 
1384
    ibuf += 2;
 
1385
 
 
1386
    memcpy(&vid, ibuf, sizeof(vid));
 
1387
    ibuf += sizeof(vid);
 
1388
 
 
1389
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
1390
        return( AFPERR_PARAM);
 
1391
    }
 
1392
 
 
1393
    if (vol->v_flags & AFPVOL_RO)
 
1394
        return AFPERR_VLOCK;
 
1395
 
 
1396
    memcpy(&did, ibuf, sizeof( did ));
 
1397
    ibuf += sizeof(did);
 
1398
 
 
1399
    if (( dir = dirlookup( vol, did )) == NULL ) {
 
1400
        return( AFPERR_PARAM );
 
1401
    }
 
1402
 
 
1403
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
1404
        return( AFPERR_PARAM );
 
1405
    }
 
1406
 
 
1407
    if ( *path == '\0' ) {
 
1408
        return( AFPERR_BADTYPE );
 
1409
    }
 
1410
 
 
1411
    upath = mtoupath(vol, path);
 
1412
    if (stat(upath, &st) < 0) {
 
1413
        switch (errno) {
 
1414
        case EPERM:
 
1415
        case EACCES:
 
1416
            return AFPERR_ACCESS;
 
1417
        case ENOENT:
 
1418
            return AFPERR_NOOBJ;
 
1419
        default:
 
1420
            return AFPERR_PARAM;
 
1421
        }
 
1422
    }
 
1423
 
 
1424
    if ((id = cnid_lookup(vol->v_db, &st, did, upath, len = strlen(upath)))) {
 
1425
        memcpy(rbuf, &id, sizeof(id));
 
1426
        *rbuflen = sizeof(id);
 
1427
        return AFPERR_EXISTID;
 
1428
    }
 
1429
 
 
1430
#if AD_VERSION > AD_VERSION1
 
1431
    memset(&ad, 0, sizeof(ad));
 
1432
    if (ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, &ad ) >= 0) {
 
1433
        memcpy(&id, ad_entry(&ad, ADEID_DID), sizeof(id));
 
1434
        ad_close(&ad, ADFLAGS_HF);
 
1435
    }
 
1436
#endif /* AD_VERSION > AD_VERSION1 */
 
1437
 
 
1438
    if ((id = cnid_add(vol->v_db, &st, did, upath, len, id)) != CNID_INVALID) {
 
1439
        memcpy(rbuf, &id, sizeof(id));
 
1440
        *rbuflen = sizeof(id);
 
1441
        return AFP_OK;
 
1442
    }
 
1443
 
 
1444
#ifdef DEBUG
 
1445
    LOG(log_info, logtype_afpd, "ending afp_createid...:");
 
1446
#endif /* DEBUG */
 
1447
 
 
1448
    switch (errno) {
 
1449
    case EROFS:
 
1450
        return AFPERR_VLOCK;
 
1451
        break;
 
1452
    case EPERM:
 
1453
    case EACCES:
 
1454
        return AFPERR_ACCESS;
 
1455
        break;
 
1456
    default:
 
1457
        LOG(log_error, logtype_afpd, "afp_createid: cnid_add: %s", strerror(errno));
 
1458
        return AFPERR_PARAM;
 
1459
    }
 
1460
}
 
1461
 
 
1462
/* resolve a file id */
 
1463
int afp_resolveid(obj, ibuf, ibuflen, rbuf, rbuflen )
 
1464
AFPObj      *obj;
 
1465
char    *ibuf, *rbuf;
 
1466
int             ibuflen, *rbuflen;
 
1467
{
 
1468
    struct stat         st;
 
1469
    struct vol          *vol;
 
1470
    struct dir          *dir;
 
1471
    char                *upath;
 
1472
    int                 err, buflen;
 
1473
    cnid_t              id;
 
1474
    u_int16_t           vid, bitmap;
 
1475
 
 
1476
    static char buffer[12 + MAXPATHLEN + 1];
 
1477
    int len = 12 + MAXPATHLEN + 1;
 
1478
 
 
1479
#ifdef DEBUG
 
1480
    LOG(log_info, logtype_afpd, "begin afp_resolveid:");
 
1481
#endif /* DEBUG */
 
1482
 
 
1483
    *rbuflen = 0;
 
1484
    ibuf += 2;
 
1485
 
 
1486
    memcpy(&vid, ibuf, sizeof(vid));
 
1487
    ibuf += sizeof(vid);
 
1488
 
 
1489
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
1490
        return( AFPERR_PARAM);
 
1491
    }
 
1492
 
 
1493
    memcpy(&id, ibuf, sizeof( id ));
 
1494
    ibuf += sizeof(id);
 
1495
 
 
1496
    if ((upath = cnid_resolve(vol->v_db, &id, buffer, len)) == NULL) {
 
1497
        return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
 
1498
    }
 
1499
 
 
1500
    if (( dir = dirlookup( vol, id )) == NULL ) {
 
1501
        return AFPERR_NOID; /* idem AFPERR_PARAM */
 
1502
    }
 
1503
 
 
1504
    if ((movecwd(vol, dir) < 0) || (stat(upath, &st) < 0)) {
 
1505
        switch (errno) {
 
1506
        case EACCES:
 
1507
        case EPERM:
 
1508
            return AFPERR_ACCESS;
 
1509
        case ENOENT:
 
1510
            return AFPERR_NOID;
 
1511
        default:
 
1512
            return AFPERR_PARAM;
 
1513
        }
 
1514
    }
 
1515
 
 
1516
    /* directories are bad */
 
1517
    if (S_ISDIR(st.st_mode))
 
1518
        return AFPERR_BADTYPE;
 
1519
 
 
1520
    memcpy(&bitmap, ibuf, sizeof(bitmap));
 
1521
    bitmap = ntohs( bitmap );
 
1522
 
 
1523
    if ((err = getfilparams(vol, bitmap, utompath(vol, upath), curdir, &st,
 
1524
                            rbuf + sizeof(bitmap), &buflen)) != AFP_OK)
 
1525
        return err;
 
1526
 
 
1527
    *rbuflen = buflen + sizeof(bitmap);
 
1528
    memcpy(rbuf, ibuf, sizeof(bitmap));
 
1529
 
 
1530
#ifdef DEBUG
 
1531
    LOG(log_info, logtype_afpd, "end afp_resolveid:");
 
1532
#endif /* DEBUG */
 
1533
 
 
1534
    return AFP_OK;
 
1535
}
 
1536
 
 
1537
int afp_deleteid(obj, ibuf, ibuflen, rbuf, rbuflen )
 
1538
AFPObj      *obj;
 
1539
char    *ibuf, *rbuf;
 
1540
int             ibuflen, *rbuflen;
 
1541
{
 
1542
    struct stat         st;
 
1543
    struct vol          *vol;
 
1544
    struct dir          *dir;
 
1545
    char                *upath;
 
1546
    int                 err;
 
1547
    cnid_t              id;
 
1548
    cnid_t              fileid;
 
1549
    u_short             vid;
 
1550
    static char buffer[12 + MAXPATHLEN + 1];
 
1551
    int len = 12 + MAXPATHLEN + 1;
 
1552
 
 
1553
#ifdef DEBUG
 
1554
    LOG(log_info, logtype_afpd, "begin afp_deleteid:");
 
1555
#endif /* DEBUG */
 
1556
 
 
1557
    *rbuflen = 0;
 
1558
    ibuf += 2;
 
1559
 
 
1560
    memcpy(&vid, ibuf, sizeof(vid));
 
1561
    ibuf += sizeof(vid);
 
1562
 
 
1563
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
1564
        return( AFPERR_PARAM);
 
1565
    }
 
1566
 
 
1567
    if (vol->v_flags & AFPVOL_RO)
 
1568
        return AFPERR_VLOCK;
 
1569
 
 
1570
    memcpy(&id, ibuf, sizeof( id ));
 
1571
    ibuf += sizeof(id);
 
1572
    fileid = id;
 
1573
 
 
1574
    if ((upath = cnid_resolve(vol->v_db, &id, buffer, len)) == NULL) {
 
1575
        return AFPERR_NOID;
 
1576
    }
 
1577
 
 
1578
    if (( dir = dirlookup( vol, id )) == NULL ) {
 
1579
        return( AFPERR_PARAM );
 
1580
    }
 
1581
 
 
1582
    err = AFP_OK;
 
1583
    if ((movecwd(vol, dir) < 0) || (stat(upath, &st) < 0)) {
 
1584
        switch (errno) {
 
1585
        case EACCES:
 
1586
        case EPERM:
 
1587
            return AFPERR_ACCESS;
 
1588
        case ENOENT:
 
1589
            /* still try to delete the id */
 
1590
            err = AFPERR_NOOBJ;
 
1591
            break;
 
1592
        default:
 
1593
            return AFPERR_PARAM;
 
1594
        }
 
1595
    }
 
1596
 
 
1597
    /* directories are bad */
 
1598
    if (S_ISDIR(st.st_mode))
 
1599
        return AFPERR_BADTYPE;
 
1600
 
 
1601
    if (cnid_delete(vol->v_db, fileid)) {
 
1602
        switch (errno) {
 
1603
        case EROFS:
 
1604
            return AFPERR_VLOCK;
 
1605
        case EPERM:
 
1606
        case EACCES:
 
1607
            return AFPERR_ACCESS;
 
1608
        default:
 
1609
            return AFPERR_PARAM;
 
1610
        }
 
1611
    }
 
1612
 
 
1613
#ifdef DEBUG
 
1614
    LOG(log_info, logtype_afpd, "end afp_deleteid:");
 
1615
#endif /* DEBUG */
 
1616
 
 
1617
    return err;
 
1618
}
 
1619
#endif /* CNID_DB */
 
1620
 
 
1621
#define APPLETEMP ".AppleTempXXXXXX"
 
1622
 
 
1623
int afp_exchangefiles(obj, ibuf, ibuflen, rbuf, rbuflen )
 
1624
AFPObj      *obj;
 
1625
char    *ibuf, *rbuf;
 
1626
int             ibuflen, *rbuflen;
 
1627
{
 
1628
    struct stat         srcst, destst;
 
1629
    struct vol          *vol;
 
1630
    struct dir          *dir, *sdir;
 
1631
    char                *spath, temp[17], *path, *p;
 
1632
    char                *supath, *upath;
 
1633
    int                 err;
 
1634
    struct adouble      ads;
 
1635
    struct adouble      add;
 
1636
    struct adouble      *adsp;
 
1637
    struct adouble      *addp;
 
1638
    struct ofork        *s_of;
 
1639
    struct ofork        *d_of;
 
1640
    
 
1641
#ifdef CNID_DB
 
1642
    int                 slen, dlen;
 
1643
#endif /* CNID_DB */
 
1644
    u_int32_t           sid, did;
 
1645
    u_int16_t           vid;
 
1646
 
 
1647
#ifdef DEBUG
 
1648
    LOG(log_info, logtype_afpd, "begin afp_exchangefiles:");
 
1649
#endif /* DEBUG */
 
1650
 
 
1651
    *rbuflen = 0;
 
1652
    ibuf += 2;
 
1653
 
 
1654
    memcpy(&vid, ibuf, sizeof(vid));
 
1655
    ibuf += sizeof(vid);
 
1656
 
 
1657
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
1658
        return( AFPERR_PARAM);
 
1659
    }
 
1660
 
 
1661
    if (vol->v_flags & AFPVOL_RO)
 
1662
        return AFPERR_VLOCK;
 
1663
 
 
1664
    /* source and destination dids */
 
1665
    memcpy(&sid, ibuf, sizeof(sid));
 
1666
    ibuf += sizeof(sid);
 
1667
    memcpy(&did, ibuf, sizeof(did));
 
1668
    ibuf += sizeof(did);
 
1669
 
 
1670
    /* source file */
 
1671
    if ((dir = dirlookup( vol, sid )) == NULL ) {
 
1672
        return( AFPERR_PARAM );
 
1673
    }
 
1674
 
 
1675
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
1676
        return( AFPERR_PARAM );
 
1677
    }
 
1678
 
 
1679
    if ( *path == '\0' ) {
 
1680
        return( AFPERR_BADTYPE );   /* it's a dir */
 
1681
    }
 
1682
 
 
1683
    upath = mtoupath(vol, path);
 
1684
    if (stat(upath, &srcst) < 0) {
 
1685
        switch (errno) {
 
1686
        case ENOENT:
 
1687
            return AFPERR_NOID;
 
1688
        case EPERM:
 
1689
        case EACCES:
 
1690
            return AFPERR_ACCESS;
 
1691
        default:
 
1692
            return AFPERR_PARAM;
 
1693
        }
 
1694
    }
 
1695
    memset(&ads, 0, sizeof(ads));
 
1696
    adsp = &ads;
 
1697
    if ((s_of = of_findname(upath, &srcst))) {
 
1698
            /* reuse struct adouble so it won't break locks */
 
1699
            adsp = s_of->of_ad;
 
1700
    }
 
1701
    /* save some stuff */
 
1702
    sdir = curdir;
 
1703
    spath = obj->oldtmp;
 
1704
    supath = obj->newtmp;
 
1705
    strcpy(spath, path);
 
1706
    strcpy(supath, upath); /* this is for the cnid changing */
 
1707
    p = ctoupath( vol, sdir, spath);
 
1708
 
 
1709
    /* look for the source cnid. if it doesn't exist, don't worry about
 
1710
     * it. */
 
1711
#ifdef CNID_DB
 
1712
    sid = cnid_lookup(vol->v_db, &srcst, sdir->d_did, supath,
 
1713
                      slen = strlen(supath));
 
1714
#endif /* CNID_DB */
 
1715
 
 
1716
    if (( dir = dirlookup( vol, did )) == NULL ) {
 
1717
        return( AFPERR_PARAM );
 
1718
    }
 
1719
 
 
1720
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
1721
        return( AFPERR_PARAM );
 
1722
    }
 
1723
 
 
1724
    if ( *path == '\0' ) {
 
1725
        return( AFPERR_BADTYPE );
 
1726
    }
 
1727
 
 
1728
    /* FPExchangeFiles is the only call that can return the SameObj
 
1729
     * error */
 
1730
    if ((curdir == sdir) && strcmp(spath, path) == 0)
 
1731
        return AFPERR_SAMEOBJ;
 
1732
 
 
1733
    upath = mtoupath(vol, path);
 
1734
    if (stat(upath, &destst) < 0) {
 
1735
        switch (errno) {
 
1736
        case ENOENT:
 
1737
            return AFPERR_NOID;
 
1738
        case EPERM:
 
1739
        case EACCES:
 
1740
            return AFPERR_ACCESS;
 
1741
        default:
 
1742
            return AFPERR_PARAM;
 
1743
        }
 
1744
    }
 
1745
    memset(&add, 0, sizeof(add));
 
1746
    addp = &add;
 
1747
    if ((d_of = of_findname( upath, &destst))) {
 
1748
            /* reuse struct adouble so it won't break locks */
 
1749
            addp = d_of->of_ad;
 
1750
    }
 
1751
 
 
1752
    /* they are not on the same device and at least one is open
 
1753
    */
 
1754
    if ((d_of || s_of)  && srcst.st_dev != destst.st_dev)
 
1755
        return AFPERR_MISC;
 
1756
    
 
1757
#ifdef CNID_DB
 
1758
    /* look for destination id. */
 
1759
    did = cnid_lookup(vol->v_db, &destst, curdir->d_did, upath,
 
1760
                      dlen = strlen(upath));
 
1761
#endif /* CNID_DB */
 
1762
 
 
1763
    /* construct a temp name.
 
1764
     * NOTE: the temp file will be in the dest file's directory. it
 
1765
     * will also be inaccessible from AFP. */
 
1766
    memcpy(temp, APPLETEMP, sizeof(APPLETEMP));
 
1767
    if (!mktemp(temp))
 
1768
        return AFPERR_MISC;
 
1769
 
 
1770
    /* now, quickly rename the file. we error if we can't. */
 
1771
    if ((err = renamefile(p, temp, temp, vol_noadouble(vol), adsp)) < 0)
 
1772
        goto err_exchangefile;
 
1773
    of_rename(vol, s_of, sdir, spath, curdir, temp);
 
1774
 
 
1775
    /* rename destination to source */
 
1776
    if ((err = renamefile(upath, p, spath, vol_noadouble(vol), addp)) < 0)
 
1777
        goto err_src_to_tmp;
 
1778
    of_rename(vol, d_of, curdir, path, sdir, spath);
 
1779
 
 
1780
    /* rename temp to destination */
 
1781
    if ((err = renamefile(temp, upath, path, vol_noadouble(vol), adsp)) < 0)
 
1782
        goto err_dest_to_src;
 
1783
    of_rename(vol, s_of, curdir, temp, curdir, path);
 
1784
 
 
1785
#ifdef CNID_DB
 
1786
    /* id's need switching. src -> dest and dest -> src. */
 
1787
    if (sid && (cnid_update(vol->v_db, sid, &destst, curdir->d_did,
 
1788
                            upath, dlen) < 0)) {
 
1789
        switch (errno) {
 
1790
        case EPERM:
 
1791
        case EACCES:
 
1792
            err = AFPERR_ACCESS;
 
1793
            break;
 
1794
        default:
 
1795
            err = AFPERR_PARAM;
 
1796
        }
 
1797
        goto err_temp_to_dest;
 
1798
    }
 
1799
 
 
1800
    if (did && (cnid_update(vol->v_db, did, &srcst, sdir->d_did,
 
1801
                            supath, slen) < 0)) {
 
1802
        switch (errno) {
 
1803
        case EPERM:
 
1804
        case EACCES:
 
1805
            err = AFPERR_ACCESS;
 
1806
            break;
 
1807
        default:
 
1808
            err = AFPERR_PARAM;
 
1809
        }
 
1810
 
 
1811
        if (sid)
 
1812
            cnid_update(vol->v_db, sid, &srcst, sdir->d_did, supath, slen);
 
1813
        goto err_temp_to_dest;
 
1814
    }
 
1815
#endif /* CNID_DB */
 
1816
 
 
1817
#ifdef DEBUG
 
1818
    LOG(log_info, logtype_afpd, "ending afp_exchangefiles:");
 
1819
#endif /* DEBUG */
 
1820
 
 
1821
    return AFP_OK;
 
1822
 
 
1823
 
 
1824
    /* all this stuff is so that we can unwind a failed operation
 
1825
     * properly. */
 
1826
#ifdef CNID_DB
 
1827
err_temp_to_dest:
 
1828
#endif
 
1829
    /* rename dest to temp */
 
1830
    renamefile(upath, temp, temp, vol_noadouble(vol), adsp);
 
1831
    of_rename(vol, s_of, curdir, upath, curdir, temp);
 
1832
 
 
1833
err_dest_to_src:
 
1834
    /* rename source back to dest */
 
1835
    renamefile(p, upath, path, vol_noadouble(vol), addp);
 
1836
    of_rename(vol, d_of, sdir, spath, curdir, path);
 
1837
 
 
1838
err_src_to_tmp:
 
1839
    /* rename temp back to source */
 
1840
    renamefile(temp, p, spath, vol_noadouble(vol), adsp);
 
1841
    of_rename(vol, s_of, curdir, temp, sdir, spath);
 
1842
 
 
1843
err_exchangefile:
 
1844
    return err;
 
1845
}