libtar version 1.2.15
[libtar.git] / lib / encode.c
blobbdd68829eddd5e4190fc53b0e3df81e96ddbe542
1 /*
2 ** Copyright 1998-2003 University of Illinois Board of Trustees
3 ** Copyright 1998-2003 Mark D. Roth
4 ** All rights reserved.
5 **
6 ** encode.c - libtar code to encode tar header blocks
7 **
8 ** Mark D. Roth <roth@uiuc.edu>
9 ** Campus Information Technologies and Educational Services
10 ** University of Illinois at Urbana-Champaign
13 #include <internal.h>
15 #include <stdio.h>
16 #include <pwd.h>
17 #include <grp.h>
18 #include <sys/types.h>
20 #ifdef STDC_HEADERS
21 # include <string.h>
22 # include <stdlib.h>
23 #endif
26 /* magic, version, and checksum */
27 void
28 th_finish(TAR *t)
30 int i, sum = 0;
32 if (t->options & TAR_GNU)
34 /* we're aiming for this result, but must do it in
35 * two calls to avoid FORTIFY segfaults on some Linux
36 * systems:
37 * strncpy(t->th_buf.magic, "ustar ", 8);
39 strncpy(t->th_buf.magic, "ustar ", 6);
40 strncpy(t->th_buf.version, " ", 2);
42 else
44 strncpy(t->th_buf.version, TVERSION, TVERSLEN);
45 strncpy(t->th_buf.magic, TMAGIC, TMAGLEN);
48 for (i = 0; i < T_BLOCKSIZE; i++)
49 sum += ((char *)(&(t->th_buf)))[i];
50 for (i = 0; i < 8; i++)
51 sum += (' ' - t->th_buf.chksum[i]);
52 int_to_oct(sum, t->th_buf.chksum, 8);
56 /* map a file mode to a typeflag */
57 void
58 th_set_type(TAR *t, mode_t mode)
60 if (S_ISLNK(mode))
61 t->th_buf.typeflag = SYMTYPE;
62 if (S_ISREG(mode))
63 t->th_buf.typeflag = REGTYPE;
64 if (S_ISDIR(mode))
65 t->th_buf.typeflag = DIRTYPE;
66 if (S_ISCHR(mode))
67 t->th_buf.typeflag = CHRTYPE;
68 if (S_ISBLK(mode))
69 t->th_buf.typeflag = BLKTYPE;
70 if (S_ISFIFO(mode) || S_ISSOCK(mode))
71 t->th_buf.typeflag = FIFOTYPE;
75 /* encode file path */
76 void
77 th_set_path(TAR *t, char *pathname)
79 char suffix[2] = "";
80 char *tmp;
82 #ifdef DEBUG
83 printf("in th_set_path(th, pathname=\"%s\")\n", pathname);
84 #endif
86 if (t->th_buf.gnu_longname != NULL)
87 free(t->th_buf.gnu_longname);
88 t->th_buf.gnu_longname = NULL;
90 if (pathname[strlen(pathname) - 1] != '/' && TH_ISDIR(t))
91 strcpy(suffix, "/");
93 if (strlen(pathname) > T_NAMELEN-1 && (t->options & TAR_GNU))
95 /* GNU-style long name */
96 t->th_buf.gnu_longname = strdup(pathname);
97 strncpy(t->th_buf.name, t->th_buf.gnu_longname, T_NAMELEN);
99 else if (strlen(pathname) > T_NAMELEN)
101 /* POSIX-style prefix field */
102 tmp = strchr(&(pathname[strlen(pathname) - T_NAMELEN - 1]), '/');
103 if (tmp == NULL)
105 printf("!!! '/' not found in \"%s\"\n", pathname);
106 return;
108 snprintf(t->th_buf.name, 100, "%s%s", &(tmp[1]), suffix);
109 snprintf(t->th_buf.prefix,
110 ((tmp - pathname + 1) <
111 155 ? (tmp - pathname + 1) : 155), "%s", pathname);
113 else
114 /* classic tar format */
115 snprintf(t->th_buf.name, 100, "%s%s", pathname, suffix);
117 #ifdef DEBUG
118 puts("returning from th_set_path()...");
119 #endif
123 /* encode link path */
124 void
125 th_set_link(TAR *t, char *linkname)
127 #ifdef DEBUG
128 printf("==> th_set_link(th, linkname=\"%s\")\n", linkname);
129 #endif
131 if (strlen(linkname) > T_NAMELEN-1 && (t->options & TAR_GNU))
133 /* GNU longlink format */
134 t->th_buf.gnu_longlink = strdup(linkname);
135 strcpy(t->th_buf.linkname, "././@LongLink");
137 else
139 /* classic tar format */
140 strlcpy(t->th_buf.linkname, linkname,
141 sizeof(t->th_buf.linkname));
142 if (t->th_buf.gnu_longlink != NULL)
143 free(t->th_buf.gnu_longlink);
144 t->th_buf.gnu_longlink = NULL;
149 /* encode device info */
150 void
151 th_set_device(TAR *t, dev_t device)
153 #ifdef DEBUG
154 printf("th_set_device(): major = %d, minor = %d\n",
155 major(device), minor(device));
156 #endif
157 int_to_oct(major(device), t->th_buf.devmajor, 8);
158 int_to_oct(minor(device), t->th_buf.devminor, 8);
162 /* encode user info */
163 void
164 th_set_user(TAR *t, uid_t uid)
166 struct passwd *pw;
168 pw = getpwuid(uid);
169 if (pw != NULL)
170 strlcpy(t->th_buf.uname, pw->pw_name, sizeof(t->th_buf.uname));
172 int_to_oct(uid, t->th_buf.uid, 8);
176 /* encode group info */
177 void
178 th_set_group(TAR *t, gid_t gid)
180 struct group *gr;
182 gr = getgrgid(gid);
183 if (gr != NULL)
184 strlcpy(t->th_buf.gname, gr->gr_name, sizeof(t->th_buf.gname));
186 int_to_oct(gid, t->th_buf.gid, 8);
190 /* encode file mode */
191 void
192 th_set_mode(TAR *t, mode_t fmode)
194 if (S_ISSOCK(fmode))
196 fmode &= ~S_IFSOCK;
197 fmode |= S_IFIFO;
199 int_to_oct(fmode, (t)->th_buf.mode, 8);
203 void
204 th_set_from_stat(TAR *t, struct stat *s)
206 th_set_type(t, s->st_mode);
207 if (S_ISCHR(s->st_mode) || S_ISBLK(s->st_mode))
208 th_set_device(t, s->st_rdev);
209 th_set_user(t, s->st_uid);
210 th_set_group(t, s->st_gid);
211 th_set_mode(t, s->st_mode);
212 th_set_mtime(t, s->st_mtime);
213 if (S_ISREG(s->st_mode))
214 th_set_size(t, s->st_size);
215 else
216 th_set_size(t, 0);