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

« back to all changes in this revision

Viewing changes to bin/afile/common.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: common.c,v 1.3 2001/06/29 14:14:46 rufustfirefly Exp $
 
3
 *
 
4
    common functions, defines, and structures for afile, achfile, and acleandir
 
5
 
 
6
    Copyright (C) 2001 Sebastian Rittau.
 
7
    All rights reserved.
 
8
 
 
9
    This file may be distributed and/or modfied under the terms of the
 
10
    following license:
 
11
 
 
12
    Redistribution and use in source and binary forms, with or without
 
13
    modification, are permitted provided that the following conditions
 
14
    are met:
 
15
    1. Redistributions of source code must retain the above copyright
 
16
       notice, this list of conditions and the following disclaimer.
 
17
    2. Redistributions in binary form must reproduce the above copyright
 
18
       notice, this list of conditions and the following disclaimer in the
 
19
       documentation and/or other materials provided with the distribution.
 
20
    3. Neither the name of the author nor the names of its contributors
 
21
       may be used to endorse or promote products derived from this software
 
22
       without specific prior written permission.
 
23
 
 
24
    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 
25
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
26
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
27
    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
28
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
29
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
30
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
31
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
32
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
33
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
34
    SUCH DAMAGE.
 
35
*/
 
36
 
 
37
#ifdef HAVE_CONFIG_H
 
38
#include "config.h"
 
39
#endif /* HAVE_CONFIG_H */
 
40
 
 
41
#include <stdlib.h>
 
42
#include <string.h>
 
43
 
 
44
#include <sys/types.h>
 
45
#include <sys/stat.h>
 
46
#ifdef HAVE_FCNTL_H
 
47
#include <fcntl.h>
 
48
#endif /* HAVE_FCNTL_H */
 
49
#ifdef HAVE_UNISTD_H
 
50
#include <unistd.h>
 
51
#endif /* HAVE_UNISTD_H */
 
52
 
 
53
#include <atalk/adouble.h>
 
54
#include <netatalk/endian.h>
 
55
 
 
56
#include "common.h"
 
57
 
 
58
 
 
59
#define AD_PREFIX ".AppleDouble/"
 
60
#define PARENT_PREFIX "../"
 
61
 
 
62
 
 
63
char *dataname_to_adname(const char *dataname)
 
64
{
 
65
  const char *filepart;
 
66
  char *adname;
 
67
  size_t adlen = strlen(AD_PREFIX);
 
68
  size_t dirlen;
 
69
 
 
70
  /* Construct the AppleDouble file name from data fork file name. */
 
71
  adname = calloc(adlen + strlen(dataname) + 1, sizeof(char));
 
72
  filepart = rindex(dataname, '/');
 
73
  if (filepart == NULL) {
 
74
    /* Filename doesn't contain a path. */
 
75
    strcpy(adname, AD_PREFIX);
 
76
    strcpy(adname + adlen, dataname);
 
77
  } else {
 
78
    /* Filename does contain a path. */
 
79
    dirlen = (size_t) (filepart - dataname);
 
80
    strncpy(adname, dataname, dirlen + 1);
 
81
    strcpy(adname + dirlen + 1, AD_PREFIX);
 
82
    strcpy(adname + dirlen + adlen + 1, filepart + 1);
 
83
  }
 
84
 
 
85
  return adname;
 
86
}
 
87
 
 
88
char *adname_to_dataname(const char *adname)
 
89
{
 
90
  const char *filepart;
 
91
  char *dataname;
 
92
  size_t plen = strlen(PARENT_PREFIX);
 
93
  size_t dirlen;
 
94
 
 
95
  /* Construct the data file name from the AppleDouble file name. */
 
96
  dataname = calloc(strlen(adname) + plen + 1, sizeof(char));
 
97
  filepart = rindex(adname, '/');
 
98
  if (filepart == NULL) {
 
99
    strcpy(dataname, PARENT_PREFIX);
 
100
    strcpy(dataname + plen, adname);
 
101
  } else {
 
102
    dirlen = (size_t) (filepart - adname);
 
103
    strncpy(dataname, adname, dirlen + 1);
 
104
    strcpy(dataname + dirlen + 1, PARENT_PREFIX);
 
105
    strcpy(dataname + dirlen + plen + 1, filepart + 1);
 
106
  }
 
107
 
 
108
  return dataname;
 
109
}
 
110
 
 
111
 
 
112
#define FLAG_NONE 0x0000
 
113
#define FLAG_AD   0x0001
 
114
#define FLAG_DIR  0x0002
 
115
 
 
116
 
 
117
struct AFile *afile_new(const char *filename)
 
118
{
 
119
  struct stat fdstat;
 
120
  char adbuf[AD_DATASZ];
 
121
  ssize_t sz;
 
122
  struct stat statbuf;
 
123
 
 
124
  struct AFile *afile = (struct AFile *) calloc(sizeof(struct AFile), 1);
 
125
  afile->filename     = filename;
 
126
  afile->fd           = open(filename, O_RDONLY);
 
127
  afile->flags        = FLAG_NONE;
 
128
 
 
129
  /* Try to open file. */
 
130
  if (afile->fd == -1) {
 
131
    free(afile);
 
132
    return NULL;
 
133
  }
 
134
 
 
135
  fstat(afile->fd, &statbuf);
 
136
  afile->mode = statbuf.st_mode;
 
137
 
 
138
  /* Try to determine if this file is a regular file, a directory, or
 
139
   * something else.
 
140
   */
 
141
  fstat(afile->fd, &fdstat);
 
142
  if (S_ISREG(fdstat.st_mode)) {                     /* it is a regular file */
 
143
    /* Check if the opened file is the resource fork. */
 
144
    sz = read(afile->fd, adbuf, AD_DATASZ);
 
145
    if (sz >= 0) {
 
146
      /* If we can't read a whole AppleDouble header, this can't be a valid
 
147
       * AppleDouble file.
 
148
       */
 
149
      if (sz == AD_DATASZ) {
 
150
        /* ... but as we could, maybe this is. Now if only the magic number
 
151
         * would be correct ...
 
152
         */
 
153
        if (ntohl(((unsigned int *) adbuf)[0]) == AD_MAGIC)
 
154
          /* Great! It obviously is a AppleDouble file. */
 
155
          afile->flags |= FLAG_AD;
 
156
          afile->creator[0] = adbuf[ADEDOFF_FINDERI + 0];
 
157
          afile->creator[1] = adbuf[ADEDOFF_FINDERI + 1];
 
158
          afile->creator[2] = adbuf[ADEDOFF_FINDERI + 2];
 
159
          afile->creator[3] = adbuf[ADEDOFF_FINDERI + 3];
 
160
          afile->type   [0] = adbuf[ADEDOFF_FINDERI + 4];
 
161
          afile->type   [1] = adbuf[ADEDOFF_FINDERI + 5];
 
162
          afile->type   [2] = adbuf[ADEDOFF_FINDERI + 6];
 
163
          afile->type   [3] = adbuf[ADEDOFF_FINDERI + 7];
 
164
      }
 
165
 
 
166
    } else {
 
167
      afile_delete(afile);
 
168
      return NULL;
 
169
    }
 
170
    
 
171
  } else if (S_ISDIR(fdstat.st_mode))                /* it is a directory */
 
172
    afile->flags |= FLAG_DIR;
 
173
  else {                                             /* it is neither */
 
174
    afile_delete(afile);
 
175
    return NULL;
 
176
  }
 
177
 
 
178
  return afile;
 
179
}
 
180
 
 
181
 
 
182
void afile_delete(struct AFile *afile)
 
183
{
 
184
  close(afile->fd);
 
185
  free(afile);
 
186
}
 
187
 
 
188
 
 
189
const char *afile_filename(struct AFile *afile)
 
190
{
 
191
  return afile->filename;
 
192
}
 
193
 
 
194
int afile_is_ad(struct AFile *afile)
 
195
{
 
196
  return afile->flags & FLAG_AD;
 
197
}
 
198
 
 
199
int afile_is_dir(struct AFile *afile)
 
200
{
 
201
  return afile->flags & FLAG_DIR;
 
202
}
 
203
 
 
204
mode_t afile_mode(struct AFile *afile)
 
205
{
 
206
  return afile->mode;
 
207
}
 
208
 
 
209
const char *afile_creator(const struct AFile *afile)
 
210
{
 
211
  return afile->creator;
 
212
}
 
213
 
 
214
const char *afile_type(const struct AFile *afile)
 
215
{
 
216
  return afile->type;
 
217
}