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

« back to all changes in this revision

Viewing changes to etc/afpd/desktop.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: desktop.c,v 1.18 2002/10/05 14:04:47 didg Exp $
 
3
 *
 
4
 * See COPYRIGHT.
 
5
 */
 
6
 
 
7
#ifdef HAVE_CONFIG_H
 
8
#include "config.h"
 
9
#endif /* HAVE_CONFIG_H */
 
10
 
 
11
#include <atalk/logger.h>
 
12
#include <errno.h>
 
13
#include <sys/types.h>
 
14
#include <sys/time.h>
 
15
#include <sys/uio.h>
 
16
#include <sys/param.h>
 
17
#include <sys/stat.h>
 
18
#include <sys/socket.h>
 
19
#include <netatalk/at.h>
 
20
#include <netatalk/endian.h>
 
21
#include <atalk/dsi.h>
 
22
#include <atalk/atp.h>
 
23
#include <atalk/asp.h>
 
24
#include <atalk/afp.h>
 
25
#include <atalk/adouble.h>
 
26
#include <atalk/util.h>
 
27
#include <dirent.h>
 
28
#ifdef HAVE_FCNTL_H
 
29
#include <fcntl.h>
 
30
#endif /* HAVE_FCNTL_H */
 
31
#include <stdio.h>
 
32
#include <string.h>
 
33
#include <ctype.h>
 
34
#ifdef HAVE_FCNTL_H
 
35
#include <unistd.h>
 
36
#endif /* HAVE_FCNTL_H */
 
37
 
 
38
#include "volume.h"
 
39
#include "directory.h"
 
40
#include "fork.h"
 
41
#include "globals.h"
 
42
#include "desktop.h"
 
43
#ifdef FILE_MANGLING
 
44
#include "mangle.h"
 
45
#endif /* CNID_DB */
 
46
 
 
47
int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
 
48
AFPObj      *obj;
 
49
char    *ibuf, *rbuf;
 
50
int             ibuflen, *rbuflen;
 
51
{
 
52
    struct vol  *vol;
 
53
    u_int16_t   vid;
 
54
 
 
55
    ibuf += 2;
 
56
 
 
57
    memcpy( &vid, ibuf, sizeof(vid));
 
58
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
59
        *rbuflen = 0;
 
60
        return( AFPERR_PARAM );
 
61
    }
 
62
 
 
63
    memcpy( rbuf, &vid, sizeof(vid));
 
64
    *rbuflen = sizeof(vid);
 
65
    return( AFP_OK );
 
66
}
 
67
 
 
68
int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
 
69
AFPObj      *obj;
 
70
char    *ibuf, *rbuf;
 
71
int             ibuflen, *rbuflen;
 
72
{
 
73
    *rbuflen = 0;
 
74
    return( AFP_OK );
 
75
}
 
76
 
 
77
struct savedt   si = { { 0, 0, 0, 0 }, -1, 0 };
 
78
 
 
79
static int iconopen( vol, creator, flags, mode )
 
80
struct vol      *vol;
 
81
u_char  creator[ 4 ];
 
82
{
 
83
    char        *dtf, *adt, *adts;
 
84
 
 
85
    if ( si.sdt_fd != -1 ) {
 
86
        if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
 
87
                si.sdt_vid == vol->v_vid ) {
 
88
            return 0;
 
89
        }
 
90
        close( si.sdt_fd );
 
91
        si.sdt_fd = -1;
 
92
    }
 
93
 
 
94
    dtf = dtfile( vol, creator, ".icon" );
 
95
 
 
96
    if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
 
97
        if ( errno == ENOENT && ( flags & O_CREAT )) {
 
98
            if (( adts = strrchr( dtf, '/' )) == NULL ) {
 
99
                return -1;
 
100
            }
 
101
            *adts = '\0';
 
102
            if (( adt = strrchr( dtf, '/' )) == NULL ) {
 
103
                return -1;
 
104
            }
 
105
            *adt = '\0';
 
106
            (void) ad_mkdir( dtf, DIRBITS | 0777 );
 
107
            *adt = '/';
 
108
            (void) ad_mkdir( dtf, DIRBITS | 0777 );
 
109
            *adts = '/';
 
110
 
 
111
            if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
 
112
                LOG(log_error, logtype_afpd, "iconopen: open %s: %s", dtf, strerror(errno) );
 
113
                return -1;
 
114
            }
 
115
        } else {
 
116
            return -1;
 
117
        }
 
118
    }
 
119
 
 
120
    memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
 
121
    si.sdt_vid = vol->v_vid;
 
122
    si.sdt_index = 1;
 
123
    return 0;
 
124
}
 
125
 
 
126
int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
 
127
AFPObj      *obj;
 
128
char    *ibuf, *rbuf;
 
129
int             ibuflen, *rbuflen;
 
130
{
 
131
    struct vol          *vol;
 
132
    struct iovec        iov[ 2 ];
 
133
    u_char              fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
 
134
    int                 itype, cc = AFP_OK, iovcnt = 0, buflen;
 
135
    u_int32_t           ftype, itag;
 
136
    u_int16_t           bsize, rsize, vid;
 
137
 
 
138
    buflen = *rbuflen;
 
139
    *rbuflen = 0;
 
140
    ibuf += 2;
 
141
 
 
142
    memcpy( &vid, ibuf, sizeof( vid ));
 
143
    ibuf += sizeof( vid );
 
144
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
145
        cc = AFPERR_PARAM;
 
146
        goto addicon_err;
 
147
    }
 
148
 
 
149
    memcpy( fcreator, ibuf, sizeof( fcreator ));
 
150
    ibuf += sizeof( fcreator );
 
151
 
 
152
    memcpy( &ftype, ibuf, sizeof( ftype ));
 
153
    ibuf += sizeof( ftype );
 
154
 
 
155
    itype = (unsigned char) *ibuf;
 
156
    ibuf += 2;
 
157
 
 
158
    memcpy( &itag, ibuf, sizeof( itag ));
 
159
    ibuf += sizeof( itag );
 
160
 
 
161
    memcpy( &bsize, ibuf, sizeof( bsize ));
 
162
    bsize = ntohs( bsize );
 
163
 
 
164
    if ( si.sdt_fd != -1 ) {
 
165
        (void)close( si.sdt_fd );
 
166
        si.sdt_fd = -1;
 
167
    }
 
168
 
 
169
    if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
 
170
        cc = AFPERR_NOITEM;
 
171
        goto addicon_err;
 
172
    }
 
173
 
 
174
    if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
 
175
        close(si.sdt_fd);
 
176
        si.sdt_fd = -1;
 
177
        LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
 
178
        cc = AFPERR_PARAM;
 
179
        goto addicon_err;
 
180
    }
 
181
 
 
182
    /*
 
183
     * Read icon elements until we find a match to replace, or
 
184
     * we get to the end to insert.
 
185
     */
 
186
    p = imh;
 
187
    memcpy( p, &itag, sizeof( itag ));
 
188
    p += sizeof( itag );
 
189
    memcpy( p, &ftype, sizeof( ftype ));
 
190
    p += sizeof( ftype );
 
191
    *p++ = itype;
 
192
    *p++ = 0;
 
193
    bsize = htons( bsize );
 
194
    memcpy( p, &bsize, sizeof( bsize ));
 
195
    bsize = ntohs( bsize );
 
196
    while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
 
197
        memcpy( &rsize, irh + 10, sizeof( rsize ));
 
198
        rsize = ntohs( rsize );
 
199
        /*
 
200
         * Is this our set of headers?
 
201
         */
 
202
        if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
 
203
            /*
 
204
             * Is the size correct?
 
205
             */
 
206
            if ( bsize != rsize )
 
207
                cc = AFPERR_ITYPE;
 
208
            break;
 
209
        }
 
210
 
 
211
        if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
 
212
            LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
 
213
            cc = AFPERR_PARAM;
 
214
        }
 
215
    }
 
216
 
 
217
    /*
 
218
     * Some error occurred, return.
 
219
     */
 
220
addicon_err:
 
221
    if ( cc < 0 ) {
 
222
        LOG(log_error, logtype_afpd, "afp_addicon: %s", strerror(errno) );
 
223
        if (obj->proto == AFPPROTO_DSI) {
 
224
            dsi_writeinit(obj->handle, rbuf, buflen);
 
225
            dsi_writeflush(obj->handle);
 
226
        }
 
227
        return cc;
 
228
    }
 
229
 
 
230
 
 
231
    switch (obj->proto) {
 
232
#ifndef NO_DDP
 
233
    case AFPPROTO_ASP:
 
234
        buflen = bsize;
 
235
        if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
 
236
            return( AFPERR_PARAM );
 
237
 
 
238
        if (obj->options.flags & OPTION_DEBUG) {
 
239
            printf("(write) len: %d\n", buflen);
 
240
            bprint(rbuf, buflen);
 
241
        }
 
242
 
 
243
        /*
 
244
         * We're at the end of the file, add the headers, etc.  */
 
245
        if ( cc == 0 ) {
 
246
            iov[ 0 ].iov_base = (caddr_t)imh;
 
247
            iov[ 0 ].iov_len = sizeof( imh );
 
248
            iov[ 1 ].iov_base = rbuf;
 
249
            iov[ 1 ].iov_len = bsize;
 
250
            iovcnt = 2;
 
251
        }
 
252
 
 
253
        /*
 
254
         * We found an icon to replace.
 
255
         */
 
256
        if ( cc > 0 ) {
 
257
            iov[ 0 ].iov_base = rbuf;
 
258
            iov[ 0 ].iov_len = bsize;
 
259
            iovcnt = 1;
 
260
        }
 
261
 
 
262
        if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
 
263
            LOG(log_error, logtype_afpd, "afp_addicon: writev: %s", strerror(errno) );
 
264
            return( AFPERR_PARAM );
 
265
        }
 
266
        break;
 
267
#endif /* no afp/asp */      
 
268
    case AFPPROTO_DSI:
 
269
        {
 
270
            DSI *dsi = obj->handle;
 
271
 
 
272
            iovcnt = dsi_writeinit(dsi, rbuf, buflen);
 
273
 
 
274
            /* add headers at end of file */
 
275
            if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
 
276
                LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
 
277
                dsi_writeflush(dsi);
 
278
                return AFPERR_PARAM;
 
279
            }
 
280
 
 
281
            if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
 
282
                LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
 
283
                dsi_writeflush(dsi);
 
284
                return AFPERR_PARAM;
 
285
            }
 
286
 
 
287
            while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
 
288
                if ( obj->options.flags & OPTION_DEBUG ) {
 
289
                    printf("(write) command cont'd: %d\n", iovcnt);
 
290
                    bprint(rbuf, iovcnt);
 
291
                }
 
292
 
 
293
                if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
 
294
                    LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
 
295
                    dsi_writeflush(dsi);
 
296
                    return AFPERR_PARAM;
 
297
                }
 
298
            }
 
299
        }
 
300
        break;
 
301
    }
 
302
 
 
303
    close( si.sdt_fd );
 
304
    si.sdt_fd = -1;
 
305
    return( AFP_OK );
 
306
}
 
307
 
 
308
u_char  utag[] = { 0, 0, 0, 0 };
 
309
u_char  ucreator[] = { 'U', 'N', 'I', 'X' };
 
310
u_char  utype[] = { 'T', 'E', 'X', 'T' };
 
311
short   usize = 256;
 
312
u_char  uicon[] = {
 
313
    0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
 
314
    0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
 
315
    0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
 
316
    0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
 
317
    0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
 
318
    0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
 
319
    0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
 
320
    0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
 
321
    0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
 
322
    0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
 
323
    0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
 
324
    0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
 
325
    0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
 
326
    0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
 
327
    0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
 
328
    0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
 
329
    0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
 
330
    0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
 
331
    0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
 
332
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
333
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
334
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
335
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
336
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
337
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
338
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
339
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
340
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
341
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
342
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
343
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
344
    0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
 
345
};
 
346
 
 
347
int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
 
348
AFPObj      *obj;
 
349
char    *ibuf, *rbuf;
 
350
int             ibuflen, *rbuflen;
 
351
{
 
352
    struct vol  *vol;
 
353
    u_char      fcreator[ 4 ], ih[ 12 ];
 
354
    u_int16_t   vid, iindex, bsize;
 
355
 
 
356
    *rbuflen = 0;
 
357
    ibuf += 2;
 
358
 
 
359
    memcpy( &vid, ibuf, sizeof( vid ));
 
360
    ibuf += sizeof( vid );
 
361
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
362
        return( AFPERR_PARAM );
 
363
    }
 
364
 
 
365
    memcpy( fcreator, ibuf, sizeof( fcreator ));
 
366
    ibuf += sizeof( fcreator );
 
367
    memcpy( &iindex, ibuf, sizeof( iindex ));
 
368
    iindex = ntohs( iindex );
 
369
 
 
370
    if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
 
371
        if ( iindex > 1 ) {
 
372
            return( AFPERR_NOITEM );
 
373
        }
 
374
        memcpy( ih, utag, sizeof( utag ));
 
375
        memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
 
376
        *( ih + sizeof( utag ) + sizeof( utype )) = 1;
 
377
        *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
 
378
        memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
 
379
                sizeof( usize ));
 
380
        memcpy( rbuf, ih, sizeof( ih ));
 
381
        *rbuflen = sizeof( ih );
 
382
        return( AFP_OK );
 
383
    }
 
384
 
 
385
    if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
 
386
        return( AFPERR_NOITEM );
 
387
    }
 
388
 
 
389
    if ( iindex < si.sdt_index ) {
 
390
        if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
 
391
            return( AFPERR_PARAM );
 
392
        }
 
393
        si.sdt_index = 1;
 
394
    }
 
395
 
 
396
    /*
 
397
     * Position to the correct spot.
 
398
     */
 
399
    for (;;) {
 
400
        if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
 
401
            close( si.sdt_fd );
 
402
            si.sdt_fd = -1;
 
403
            return( AFPERR_NOITEM );
 
404
        }
 
405
        memcpy( &bsize, ih + 10, sizeof( bsize ));
 
406
        bsize = ntohs(bsize);
 
407
        if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
 
408
            LOG(log_error, logtype_afpd, "afp_iconinfo: lseek: %s", strerror(errno) );
 
409
            return( AFPERR_PARAM );
 
410
        }
 
411
        if ( si.sdt_index == iindex ) {
 
412
            memcpy( rbuf, ih, sizeof( ih ));
 
413
            *rbuflen = sizeof( ih );
 
414
            return( AFP_OK );
 
415
        }
 
416
        si.sdt_index++;
 
417
    }
 
418
}
 
419
 
 
420
 
 
421
int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
 
422
AFPObj      *obj;
 
423
char    *ibuf, *rbuf;
 
424
int             ibuflen, *rbuflen;
 
425
{
 
426
    struct vol  *vol;
 
427
    off_t       offset;
 
428
    int         rc, buflen;
 
429
    u_char      fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
 
430
    u_int16_t   vid, bsize, rsize;
 
431
 
 
432
    buflen = *rbuflen;
 
433
    *rbuflen = 0;
 
434
    ibuf += 2;
 
435
 
 
436
    memcpy( &vid, ibuf, sizeof( vid ));
 
437
    ibuf += sizeof( vid );
 
438
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
439
        return( AFPERR_PARAM );
 
440
    }
 
441
 
 
442
    memcpy( fcreator, ibuf, sizeof( fcreator ));
 
443
    ibuf += sizeof( fcreator );
 
444
    memcpy( ftype, ibuf, sizeof( ftype ));
 
445
    ibuf += sizeof( ftype );
 
446
    itype = (unsigned char) *ibuf++;
 
447
    ibuf++;
 
448
    memcpy( &bsize, ibuf, sizeof( bsize ));
 
449
    bsize = ntohs( bsize );
 
450
 
 
451
    if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
 
452
            memcmp( ftype, utype, sizeof( utype )) == 0 &&
 
453
            itype == 1 &&
 
454
            bsize <= usize ) {
 
455
        memcpy( rbuf, uicon, bsize);
 
456
        *rbuflen = bsize;
 
457
        return( AFP_OK );
 
458
    }
 
459
 
 
460
    if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
 
461
        return( AFPERR_NOITEM );
 
462
    }
 
463
 
 
464
    if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
 
465
        close(si.sdt_fd);
 
466
        si.sdt_fd = -1;
 
467
        LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno));
 
468
        return( AFPERR_PARAM );
 
469
    }
 
470
 
 
471
    si.sdt_index = 1;
 
472
    offset = 0;
 
473
    while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
 
474
        si.sdt_index++;
 
475
        offset += sizeof(ih);
 
476
        if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
 
477
                *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
 
478
            break;
 
479
        }
 
480
        memcpy( &rsize, ih + 10, sizeof( rsize ));
 
481
        rsize = ntohs( rsize );
 
482
        if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
 
483
            LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno) );
 
484
            return( AFPERR_PARAM );
 
485
        }
 
486
        offset += rsize;
 
487
    }
 
488
 
 
489
    if ( rc < 0 ) {
 
490
        LOG(log_error, logtype_afpd, "afp_geticon: read: %s", strerror(errno));
 
491
        return( AFPERR_PARAM );
 
492
    }
 
493
 
 
494
    if ( rc == 0 ) {
 
495
        return( AFPERR_NOITEM );
 
496
    }
 
497
 
 
498
    memcpy( &rsize, ih + 10, sizeof( rsize ));
 
499
    rsize = ntohs( rsize );
 
500
#define min(a,b)        ((a)<(b)?(a):(b))
 
501
    rc = min( bsize, rsize );
 
502
 
 
503
    if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
 
504
        DSI *dsi = obj->handle;
 
505
        struct stat st;
 
506
        off_t size;
 
507
 
 
508
        size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
 
509
        if (size < rc + offset) {
 
510
            return AFPERR_PARAM;
 
511
        }
 
512
 
 
513
        if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
 
514
            goto geticon_exit;
 
515
 
 
516
        /* do to the streaming nature, we have to exit if we encounter
 
517
         * a problem. much confusion results otherwise. */
 
518
        while (*rbuflen > 0) {
 
519
#if defined(SENDFILE_FLAVOR_LINUX) || defined(SENDFILE_FLAVOR_BSD)
 
520
            if (!obj->options.flags & OPTION_DEBUG) {
 
521
#ifdef SENDFILE_FLAVOR_LINUX
 
522
                if (sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0)
 
523
                    goto geticon_exit;
 
524
#endif /* SENDFILE_FLAVOR_LINUX */
 
525
 
 
526
#ifdef SENDFILE_FLAVOR_BSD
 
527
                if (sendfile(si.sdt_fd, dsi->socket, offset, rc, NULL, NULL, 0) < 0)
 
528
                    goto geticon_exit;
 
529
#endif /* SENDFILE_FLAVOR_BSD */
 
530
 
 
531
                goto geticon_done;
 
532
            }
 
533
#endif /* SENDFILE_FLAVOR_LINUX || SENDFILE_FLAVOR_BSD */
 
534
 
 
535
            buflen = read(si.sdt_fd, rbuf, *rbuflen);
 
536
            if (buflen < 0)
 
537
                goto geticon_exit;
 
538
 
 
539
            if (obj->options.flags & OPTION_DEBUG) {
 
540
                printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
 
541
                bprint(rbuf, buflen);
 
542
            }
 
543
 
 
544
            /* dsi_read() also returns buffer size of next allocation */
 
545
            buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
 
546
            if (buflen < 0)
 
547
                goto geticon_exit;
 
548
 
 
549
            *rbuflen = buflen;
 
550
        }
 
551
 
 
552
geticon_done:
 
553
        dsi_readdone(dsi);
 
554
        return AFP_OK;
 
555
 
 
556
geticon_exit:
 
557
        LOG(log_info, logtype_afpd, "afp_geticon: %s", strerror(errno));
 
558
        dsi_readdone(dsi);
 
559
        obj->exit(1);
 
560
        return AFP_OK;
 
561
 
 
562
    } else {
 
563
        if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
 
564
            return( AFPERR_PARAM );
 
565
        }
 
566
        *rbuflen = rc;
 
567
        return AFP_OK;
 
568
    }
 
569
}
 
570
 
 
571
 
 
572
static char             hexdig[] = "0123456789abcdef";
 
573
char *dtfile(const struct vol *vol, u_char creator[], char *ext )
 
574
{
 
575
    static char path[ MAXPATHLEN + 1];
 
576
    char        *p;
 
577
    int         i;
 
578
 
 
579
    strcpy( path, vol->v_path );
 
580
    strcat( path, "/.AppleDesktop/" );
 
581
    for ( p = path; *p != '\0'; p++ )
 
582
        ;
 
583
 
 
584
    if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
 
585
        *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
 
586
        *p++ = hexdig[ creator[ 0 ] & 0x0f ];
 
587
    } else {
 
588
        *p++ = creator[ 0 ];
 
589
    }
 
590
 
 
591
    *p++ = '/';
 
592
 
 
593
    for ( i = 0; i < sizeof( CreatorType ); i++ ) {
 
594
        if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
 
595
            *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
 
596
            *p++ = hexdig[ creator[ i ] & 0x0f ];
 
597
        } else {
 
598
            *p++ = creator[ i ];
 
599
        }
 
600
    }
 
601
    *p = '\0';
 
602
    strcat( path, ext );
 
603
 
 
604
    return( path );
 
605
}
 
606
 
 
607
char *mtoupath(const struct vol *vol, char *mpath)
 
608
{
 
609
    static char  upath[ MAXPATHLEN + 1];
 
610
    char        *m, *u;
 
611
    int          i = 0;
 
612
 
 
613
    if ( *mpath == '\0' ) {
 
614
        return( "." );
 
615
    }
 
616
 
 
617
#ifdef FILE_MANGLING
 
618
    mpath = demangle(vol, mpath);
 
619
#endif /* FILE_MANGLING */
 
620
 
 
621
    m = mpath;
 
622
    u = upath;
 
623
    while ( *m != '\0' ) {
 
624
        /* handle case conversion first */
 
625
        if (vol->v_casefold & AFPVOL_MTOUUPPER)
 
626
            *m = diatoupper( *m );
 
627
        else if (vol->v_casefold & AFPVOL_MTOULOWER)
 
628
            *m = diatolower( *m );
 
629
 
 
630
        /* we have a code page. we only use the ascii range
 
631
         * if we have map ascii specified. */
 
632
#if 1
 
633
        if (vol->v_mtoupage && ((*m & 0x80) ||
 
634
                                vol->v_flags & AFPVOL_MAPASCII)) {
 
635
            *u = vol->v_mtoupage->map[(unsigned char) *m].value;
 
636
            if (!*u && *m) {
 
637
                /* if conversion failed, encode in hex
 
638
                 * to prevent silly truncation
 
639
                 * H.P. Jansen <hpj@urpla.net> */
 
640
#ifdef DEBUG
 
641
                LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
 
642
#endif /* DEBUG */
 
643
                *u++ = ':';
 
644
                *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
 
645
                *u = hexdig[ *m & 0x0f ];
 
646
            }
 
647
        } else
 
648
#endif /* 1 */
 
649
#if AD_VERSION == AD_VERSION1
 
650
            if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
 
651
                    (!isascii(*m) || *m == '/')) ||
 
652
                    (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
 
653
                     ( i == 0 && (*m == '.' )))) {
 
654
#else /* AD_VERSION == AD_VERSION1 */
 
655
            if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
 
656
                    (!isprint(*m) || *m == '/')) ||
 
657
                    (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
 
658
                     ( i == 0 && (*m == '.' )))) {
 
659
#endif /* AD_VERSION == AD_VERSION1 */
 
660
                /* do hex conversion. */
 
661
                *u++ = ':';
 
662
                *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
 
663
                *u = hexdig[ *m & 0x0f ];
 
664
            } else
 
665
                *u = *m;
 
666
        u++;
 
667
        i++;
 
668
        m++;
 
669
    }
 
670
    *u = '\0';
 
671
 
 
672
#ifdef DEBUG
 
673
    LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
 
674
#endif /* DEBUG */
 
675
 
 
676
    return( upath );
 
677
}
 
678
 
 
679
#define hextoint( c )   ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
 
680
#define islxdigit(x)    (!isupper(x)&&isxdigit(x))
 
681
 
 
682
char *utompath(const struct vol *vol, char *upath)
 
683
{
 
684
    static char  mpath[ MAXPATHLEN + 1];
 
685
    char        *m, *u;
 
686
    int          h;
 
687
 
 
688
    /* do the hex conversion */
 
689
    u = upath;
 
690
    m = mpath;
 
691
    while ( *u != '\0' ) {
 
692
        /* we have a code page */
 
693
#if 1
 
694
        if (vol->v_utompage && ((*u & 0x80) ||
 
695
                                (vol->v_flags & AFPVOL_MAPASCII))) {
 
696
            *m = vol->v_utompage->map[(unsigned char) *u].value;
 
697
        } else
 
698
#endif /* 1 */
 
699
            if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
 
700
                    *(u+2) != '\0' && islxdigit( *(u+2))) {
 
701
                ++u;
 
702
                h = hextoint( *u ) << 4;
 
703
                ++u;
 
704
                h |= hextoint( *u );
 
705
                *m = h;
 
706
            } else
 
707
                *m = *u;
 
708
 
 
709
        /* handle case conversion */
 
710
        if (vol->v_casefold & AFPVOL_UTOMLOWER)
 
711
            *m = diatolower( *m );
 
712
        else if (vol->v_casefold & AFPVOL_UTOMUPPER)
 
713
            *m = diatoupper( *m );
 
714
 
 
715
        u++;
 
716
        m++;
 
717
    }
 
718
    *m = '\0';
 
719
 
 
720
#ifdef FILE_MANGLING
 
721
    strcpy(mpath,mangle(vol, mpath));
 
722
#endif /* FILE_MANGLING */
 
723
 
 
724
#ifdef DEBUG
 
725
    LOG(log_debug, logtype_afpd, "utompath: '%s':'%s'", upath, mpath);
 
726
#endif /* DEBUG */
 
727
 
 
728
    return( mpath );
 
729
}
 
730
 
 
731
int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
 
732
AFPObj      *obj;
 
733
char    *ibuf, *rbuf;
 
734
int             ibuflen, *rbuflen;
 
735
{
 
736
    struct adouble      ad, *adp;
 
737
    struct vol          *vol;
 
738
    struct dir          *dir;
 
739
    struct ofork        *of;
 
740
    char                *path, *name, *upath;
 
741
    int                 clen;
 
742
    u_int32_t           did;
 
743
    u_int16_t           vid;
 
744
 
 
745
    *rbuflen = 0;
 
746
    ibuf += 2;
 
747
 
 
748
    memcpy( &vid, ibuf, sizeof( vid ));
 
749
    ibuf += sizeof( vid );
 
750
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
751
        return( AFPERR_PARAM );
 
752
    }
 
753
 
 
754
    memcpy( &did, ibuf, sizeof( did ));
 
755
    ibuf += sizeof( did );
 
756
    if (( dir = dirlookup( vol, did )) == NULL ) {
 
757
        return( AFPERR_NOOBJ );
 
758
    }
 
759
 
 
760
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
761
        return( AFPERR_NOOBJ );
 
762
    }
 
763
 
 
764
    if ((u_long)ibuf & 1 ) {
 
765
        ibuf++;
 
766
    }
 
767
 
 
768
    clen = (u_char)*ibuf++;
 
769
    clen = min( clen, 199 );
 
770
    upath = mtoupath( vol, path );
 
771
    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
 
772
        memset(&ad, 0, sizeof(ad));
 
773
        adp = &ad;
 
774
    } else
 
775
        adp = of->of_ad;
 
776
    if (ad_open( upath , vol_noadouble(vol) |
 
777
                 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
 
778
                 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
 
779
        return( AFPERR_ACCESS );
 
780
    }
 
781
 
 
782
    if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
 
783
        if ( *path == '\0' ) {
 
784
            name = curdir->d_name;
 
785
        } else {
 
786
            name = path;
 
787
        }
 
788
        ad_setentrylen( adp, ADEID_NAME, strlen( name ));
 
789
        memcpy( ad_entry( adp, ADEID_NAME ), name,
 
790
                ad_getentrylen( adp, ADEID_NAME ));
 
791
    }
 
792
 
 
793
    ad_setentrylen( adp, ADEID_COMMENT, clen );
 
794
    memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
 
795
    ad_flush( adp, ADFLAGS_HF );
 
796
    ad_close( adp, ADFLAGS_HF );
 
797
    return( AFP_OK );
 
798
}
 
799
 
 
800
int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
 
801
AFPObj      *obj;
 
802
char    *ibuf, *rbuf;
 
803
int             ibuflen, *rbuflen;
 
804
{
 
805
    struct adouble      ad, *adp;
 
806
    struct vol          *vol;
 
807
    struct dir          *dir;
 
808
    struct ofork        *of;
 
809
    char                *path, *upath;
 
810
    u_int32_t           did;
 
811
    u_int16_t           vid;
 
812
 
 
813
    *rbuflen = 0;
 
814
    ibuf += 2;
 
815
 
 
816
    memcpy( &vid, ibuf, sizeof( vid ));
 
817
    ibuf += sizeof( vid );
 
818
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
819
        return( AFPERR_PARAM );
 
820
    }
 
821
 
 
822
    memcpy( &did, ibuf, sizeof( did ));
 
823
    ibuf += sizeof( did );
 
824
    if (( dir = dirlookup( vol, did )) == NULL ) {
 
825
        return( AFPERR_NOOBJ );
 
826
    }
 
827
 
 
828
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
829
        return( AFPERR_NOOBJ );
 
830
    }
 
831
 
 
832
 
 
833
    upath = mtoupath( vol, path );
 
834
    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
 
835
        memset(&ad, 0, sizeof(ad));
 
836
        adp = &ad;
 
837
    } else
 
838
        adp = of->of_ad;
 
839
    if ( ad_open( upath,
 
840
                  (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
 
841
                  O_RDONLY, 0666, adp) < 0 ) {
 
842
        return( AFPERR_NOITEM );
 
843
    }
 
844
 
 
845
    /*
 
846
     * Make sure the AD file is not bogus.
 
847
     */
 
848
    if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
 
849
            ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
 
850
        ad_close( adp, ADFLAGS_HF );
 
851
        return( AFPERR_NOITEM );
 
852
    }
 
853
 
 
854
    *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
 
855
    memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
 
856
            ad_getentrylen( adp, ADEID_COMMENT ));
 
857
    *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
 
858
    ad_close( adp, ADFLAGS_HF );
 
859
    return( AFP_OK );
 
860
}
 
861
 
 
862
int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
 
863
AFPObj      *obj;
 
864
char    *ibuf, *rbuf;
 
865
int             ibuflen, *rbuflen;
 
866
{
 
867
    struct adouble      ad, *adp;
 
868
    struct vol          *vol;
 
869
    struct dir          *dir;
 
870
    struct ofork        *of;
 
871
    char                *path, *upath;
 
872
    u_int32_t           did;
 
873
    u_int16_t           vid;
 
874
 
 
875
    *rbuflen = 0;
 
876
    ibuf += 2;
 
877
 
 
878
    memcpy( &vid, ibuf, sizeof( vid ));
 
879
    ibuf += sizeof( vid );
 
880
    if (( vol = getvolbyvid( vid )) == NULL ) {
 
881
        return( AFPERR_PARAM );
 
882
    }
 
883
 
 
884
    memcpy( &did, ibuf, sizeof( did ));
 
885
    ibuf += sizeof( did );
 
886
    if (( dir = dirlookup( vol, did )) == NULL ) {
 
887
        return( AFPERR_NOOBJ );
 
888
    }
 
889
 
 
890
    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
 
891
        return( AFPERR_NOOBJ );
 
892
    }
 
893
 
 
894
    upath = mtoupath( vol, path );
 
895
    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
 
896
        memset(&ad, 0, sizeof(ad));
 
897
        adp = &ad;
 
898
    } else
 
899
        adp = of->of_ad;
 
900
 
 
901
    if ( ad_open( upath,
 
902
                  (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
 
903
                  O_RDWR, 0, adp) < 0 ) {
 
904
        switch ( errno ) {
 
905
        case ENOENT :
 
906
            return( AFPERR_NOITEM );
 
907
        case EACCES :
 
908
            return( AFPERR_ACCESS );
 
909
        default :
 
910
            return( AFPERR_PARAM );
 
911
        }
 
912
    }
 
913
 
 
914
    ad_setentrylen( adp, ADEID_COMMENT, 0 );
 
915
    ad_flush( adp, ADFLAGS_HF );
 
916
    ad_close( adp, ADFLAGS_HF );
 
917
    return( AFP_OK );
 
918
}