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

« back to all changes in this revision

Viewing changes to bin/afile/achfile.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: achfile.c,v 1.5 2001/10/19 02:39:07 jmarcus Exp $
 
3
 *
 
4
    afile - determine the MacOS creator/type of files
 
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 <stdio.h>
 
42
#include <string.h>
 
43
#include <errno.h>
 
44
 
 
45
#include <sys/types.h>
 
46
#include <sys/stat.h>
 
47
#ifdef HAVE_FCNTL_H
 
48
#include <fcntl.h>
 
49
#endif /* HAVE_FCNTL_H */
 
50
#ifdef HAVE_UNISTD_H
 
51
#include <unistd.h>
 
52
#endif /* HAVE_UNISTD_H */
 
53
 
 
54
#include <atalk/adouble.h>
 
55
 
 
56
#include "common.h"
 
57
 
 
58
/* Global Variables */
 
59
const char *type    = NULL;
 
60
const char *creator = NULL;
 
61
 
 
62
 
 
63
/* Print usage information. */
 
64
void usage(char *prog)
 
65
{
 
66
  fprintf(stderr, "Usage: %s [-t TYPE] [-c CREATOR] FILE ...\n", prog);
 
67
}
 
68
 
 
69
/* Print extensive help. */
 
70
void help(char *prog)
 
71
{
 
72
  usage(prog);
 
73
  fprintf(stderr,
 
74
          "\n"
 
75
          "Change the MacOS creator/type of FILEs.\n"
 
76
          "\n"
 
77
          "  -t, --type=TYPE        choose type\n"
 
78
          "  -c, --creator=CREATOR  choose creator\n"
 
79
          "  -h, --help             show this help and exit\n"
 
80
          "  -v, --version          show version information and exit\n");
 
81
}
 
82
 
 
83
/* Print the version. */
 
84
void version()
 
85
{
 
86
  fprintf(stderr, "achfile (netatalk " VERSION ")\n");
 
87
}
 
88
 
 
89
/* Argument Handling
 
90
 * known options: -t, -c, -h, -v
 
91
 * known long options: --help, --version
 
92
 */
 
93
#define OPTSTRING "t:c:hv-:"
 
94
const char *get_long_arg(int argc, char *argv[], const char *arg, const char *oa) {
 
95
  switch (*oa) {
 
96
  case '=':
 
97
    return &oa[1];
 
98
  case '\0':
 
99
    if (optind == argc) {
 
100
      fprintf(stderr, "%s: option \'%s\' requires an argument\n", argv[0], arg);
 
101
      return NULL;
 
102
    }
 
103
    return argv[optind++];
 
104
  default:
 
105
    fprintf(stderr, "%s: unrecognized option \'%s\'\n", argv[0], arg);
 
106
    usage(argv[0]);
 
107
    return NULL;
 
108
  }
 
109
}
 
110
 
 
111
int parse_args(int argc, char *argv[])
 
112
{
 
113
  int c;
 
114
  const char *longarg;
 
115
 
 
116
  /* iterate through the command line */
 
117
  while ((c = getopt(argc, argv, OPTSTRING)) != -1) {
 
118
    switch (c) {
 
119
    case 'h':
 
120
      help(argv[0]);
 
121
      exit(0);
 
122
    case 'v':
 
123
      version();
 
124
      exit(0);
 
125
    case 't':
 
126
      type = optarg;
 
127
      break;
 
128
    case 'c':
 
129
      creator = optarg;
 
130
      break;
 
131
    case '-':
 
132
      if (strcmp(optarg, "help") == 0) {
 
133
        help(argv[0]);
 
134
        exit(0);
 
135
      }
 
136
      if (strcmp(optarg, "version") == 0) {
 
137
        version();
 
138
        exit(0);
 
139
      }
 
140
      if (strncmp(optarg, "type", 4) == 0) {
 
141
        longarg = get_long_arg(argc, argv, "type", &optarg[4]);
 
142
        if (!longarg)
 
143
          return -1;
 
144
        type = longarg;
 
145
      } else if (strncmp(optarg, "creator", 7) == 0) {
 
146
        longarg = get_long_arg(argc, argv, "creator", &optarg[7]);
 
147
        if (!longarg)
 
148
          return -1;
 
149
        creator = longarg;
 
150
      }
 
151
      break;
 
152
    default:
 
153
      usage(argv[0]);
 
154
      return -1;
 
155
    }
 
156
  }
 
157
 
 
158
  /* At least one file argument is required. */
 
159
  if (argc == optind) {
 
160
    usage(argv[0]);
 
161
    return -1;
 
162
  }
 
163
 
 
164
  /* Either type or creator is required. */
 
165
  if (!type && !creator) {
 
166
    fprintf(stderr, "achfile: either type or creator must be specified\n");
 
167
    return -1;
 
168
  }
 
169
 
 
170
  /* Type and creator must be exactly four characters long. */
 
171
  if ((type && strlen(type) != 4) || (creator && strlen(creator) != 4)) {
 
172
    fprintf(stderr, "achfile: type and creator must be four character IDs\n");
 
173
    return -1;
 
174
  }
 
175
 
 
176
  return 0;
 
177
}
 
178
 
 
179
 
 
180
/* Change the owner/creator of each file specified on the command line. */
 
181
int handle_file(const char *filename)
 
182
{
 
183
  int fd;
 
184
  struct stat statbuf;
 
185
  char *adname;
 
186
  ssize_t sz;
 
187
  char buf[AD_DATASZ];
 
188
  struct adouble *ad = (struct adouble *) &buf;
 
189
 
 
190
  if (stat(filename, &statbuf) == -1) {
 
191
    fprintf(stderr, "achfile:%s: %s\n", filename, strerror(errno));
 
192
    return -1;
 
193
  }
 
194
 
 
195
  adname = dataname_to_adname(filename);
 
196
  fd = open(adname, O_RDWR, 0);
 
197
  if (fd == -1) {
 
198
    if (errno == ENOENT)
 
199
      fprintf(stderr, "achfile:%s: no resource fork\n", filename);
 
200
    else
 
201
      fprintf(stderr, "achfile:%s: %s\n", adname, strerror(errno));
 
202
    free(adname);
 
203
    return -1;
 
204
  }
 
205
  sz = read(fd, buf, AD_DATASZ);
 
206
  if (sz == -1) {
 
207
    fprintf(stderr, "achfile:%s: %s\n", adname, strerror(errno));
 
208
    free(adname);
 
209
    close(fd);
 
210
    return -1;
 
211
  } else if (sz < AD_DATASZ) {
 
212
    fprintf(stderr, "achfile:%s: corrupt resource fork\n", filename);
 
213
    free(adname);
 
214
    close(fd);
 
215
    return -1;
 
216
  }
 
217
  if ( ntohl(ad->ad_magic) != AD_MAGIC) {
 
218
    fprintf(stderr, "achfile:%s: corrupt resource fork\n", filename);
 
219
    free(adname);
 
220
    close(fd);
 
221
    return -1;
 
222
  }
 
223
 
 
224
  /* Change Type */
 
225
  if (type) {
 
226
    buf[ADEDOFF_FINDERI + 0] = type[0];
 
227
    buf[ADEDOFF_FINDERI + 1] = type[1];
 
228
    buf[ADEDOFF_FINDERI + 2] = type[2];
 
229
    buf[ADEDOFF_FINDERI + 3] = type[3];
 
230
 }
 
231
 
 
232
  /* Change Creator */
 
233
  if (creator) {
 
234
    buf[ADEDOFF_FINDERI + 4] = creator[0];
 
235
    buf[ADEDOFF_FINDERI + 5] = creator[1];
 
236
    buf[ADEDOFF_FINDERI + 6] = creator[2];
 
237
    buf[ADEDOFF_FINDERI + 7] = creator[3];
 
238
 }
 
239
 
 
240
  /* Write file back to disk. */
 
241
  if (lseek(fd, 0, SEEK_SET) == -1) {
 
242
    fprintf(stderr, "achfile:%s: %s\n", adname, strerror(errno));
 
243
    free(adname);
 
244
    close(fd);
 
245
    return -1;
 
246
  }
 
247
  if (write(fd, &buf, AD_DATASZ) < AD_DATASZ) {
 
248
    fprintf(stderr, "achfile:%s: %s\n", adname, strerror(errno));
 
249
    free(adname);
 
250
    close(fd);
 
251
    return -1;
 
252
  }
 
253
 
 
254
  /* Clean Up */
 
255
  free(adname);
 
256
  close(fd);
 
257
 
 
258
  return 0;
 
259
}
 
260
 
 
261
 
 
262
int main(int argc, char *argv[])
 
263
{
 
264
  /* argument handling */
 
265
  if (parse_args(argc, argv) == -1)
 
266
    return 1;
 
267
 
 
268
  while (optind < argc)
 
269
    handle_file(argv[optind++]);
 
270
 
 
271
  return 0;
 
272
}