source: trunk/third/moira/gen/tar.c @ 24319

Revision 24319, 3.8 KB checked in by broder, 14 years ago (diff)
New Moira snapshot from SVN.
Line 
1/* $Id: tar.c 3956 2010-01-05 20:56:56Z zacheiss $
2 *
3 * Utility routines for writing tar files.
4 *
5 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
8 */
9
10#include <mit-copyright.h>
11#include <moira.h>
12#include <moira_site.h>
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include "util.h"
19
20RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/gen/tar.c $ $Id: tar.c 3956 2010-01-05 20:56:56Z zacheiss $");
21
22static char tar_zeros[512];
23
24TARFILE *tarfile_open(char *file)
25{
26  TARFILE *tf;
27
28  tf = malloc(sizeof(TARFILE));
29  if (!tf)
30    {
31      perror("couldn't open tarfile");
32      exit(MR_OCONFIG);
33    }
34
35  tf->fp = fopen(file, "w");
36  if (!tf->fp)
37    {
38      perror("couldn't open tarfile");
39      exit(MR_OCONFIG);
40    }
41
42  return tf;
43}
44
45void tarfile_close(TARFILE *tf)
46{
47  long offset;
48  int blocks;
49
50  offset = ftell(tf->fp);
51  /* The tar file must have two empty 512-byte blocks at the end, and
52   * then must be padded to a multiple of 20 512-byte blocks. This
53   * calculates how many blocks to add.
54   */
55  blocks = (20 - ((offset / 512) + 2) % 20) + 2;
56
57  while (blocks--)
58    {
59      if (fwrite(tar_zeros, 512, 1, tf->fp) != 1)
60        {
61          perror("could not write last tarfile block");
62          exit(MR_OCONFIG);
63        }
64    }
65
66  fclose(tf->fp);
67  free(tf);
68}
69
70FILE *tarfile_start(TARFILE *tf, char *name, mode_t mode, uid_t uid, gid_t gid,
71                    char *user, char *group, time_t mtime)
72{
73  memset(&(tf->th), 0, sizeof(tf->th));
74  memset(tf->th.chksum, ' ', sizeof(tf->th.chksum));
75  strcpy(tf->th.name, (name[0] == '/' ? name + 1 : name));
76  sprintf(tf->th.mode, "%07lo", (unsigned long)mode);
77  sprintf(tf->th.uid, "%07lo", (unsigned long)uid);
78  sprintf(tf->th.gid, "%07lo", (unsigned long)gid);
79  sprintf(tf->th.mtime, "%011lo", (unsigned long)mtime);
80  tf->th.typeflag[0] = '0';
81  sprintf(tf->th.magic, "ustar");
82  sprintf(tf->th.version, "00");
83  sprintf(tf->th.uname, "%.32s", user);
84  sprintf(tf->th.gname, "%.32s", group);
85
86  tf->offset = ftell(tf->fp);
87
88  if (fwrite(&(tf->th), sizeof(tf->th), 1, tf->fp) != 1)
89    {
90      perror("could not write tarfile header");
91      exit(MR_OCONFIG);
92    }
93  return tf->fp;
94}
95
96void tarfile_end(TARFILE *tf)
97{
98  long offset = ftell(tf->fp);
99  unsigned long size;
100  int chksum = 0;
101  char *p;
102
103  size = offset - tf->offset;
104  if (size % 512)
105    {
106      if (fwrite(tar_zeros, 512 - (size % 512), 1, tf->fp) != 1)
107        goto err;
108    }
109  sprintf(tf->th.size, "%011lo", size - 512);
110
111  for (p = (char *)&(tf->th); p < (char *)(&(tf->th) + 1); p++)
112    chksum += (unsigned char)*p;
113  sprintf(tf->th.chksum, "%07lo", chksum);
114
115  if (fseek(tf->fp, tf->offset, SEEK_SET))
116    goto err;
117  if (fwrite(&(tf->th), sizeof(tf->th), 1, tf->fp) != 1)
118    goto err;
119  if (fseek(tf->fp, 0, SEEK_END))
120    goto err;
121
122  return;
123
124err:
125  perror("could not finish tarfile entry");
126  exit(MR_OCONFIG);
127}
128
129void tarfile_mkdir(TARFILE *tf, char *name, mode_t mode, uid_t uid, gid_t gid,
130                   char *user, char *group, time_t mtime)
131{
132  struct tarheader th;
133  char *p;
134  int chksum = 0;
135
136  memset(&th, 0, sizeof(th));
137  memset(th.chksum, ' ', sizeof(th.chksum));
138  strcpy(th.name, name);
139  sprintf(th.mode, "%07lo", (unsigned long)mode);
140  sprintf(th.uid, "%07lo", (unsigned long)uid);
141  sprintf(th.gid, "%07lo", (unsigned long)gid);
142  sprintf(th.size, "%011lo", (unsigned long)0);
143  sprintf(th.mtime, "%011lo", (unsigned long)mtime);
144  th.typeflag[0] = '5';
145  sprintf(th.magic, "ustar");
146  sprintf(th.version, "00");
147  sprintf(th.uname, "%.32s", user);
148  sprintf(th.gname, "%.32s", group);
149
150  for (p = (char *)&th; p < (char *)(&th + 1); p++)
151    chksum += (unsigned char)*p;
152  sprintf(th.chksum, "%07lo", chksum);
153
154  if (fwrite(&th, sizeof(th), 1, tf->fp) != 1)
155    {
156      perror("could not write tarfile header");
157      exit(MR_OCONFIG);
158    }
159}
Note: See TracBrowser for help on using the repository browser.