tarruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.txt +99 -0
- data/ext/extconf.rb +19 -0
- data/ext/libtar/COPYRIGHT +35 -0
- data/ext/libtar/ChangeLog +243 -0
- data/ext/libtar/ChangeLog-1.0.x +141 -0
- data/ext/libtar/INSTALL +183 -0
- data/ext/libtar/Makefile.in +51 -0
- data/ext/libtar/README +121 -0
- data/ext/libtar/TODO +10 -0
- data/ext/libtar/autoconf/ac_path_generic.m4 +136 -0
- data/ext/libtar/autoconf/aclocal.m4 +199 -0
- data/ext/libtar/autoconf/encap.m4 +133 -0
- data/ext/libtar/autoconf/install-sh +251 -0
- data/ext/libtar/autom4te.cache/output.0 +8102 -0
- data/ext/libtar/autom4te.cache/requests +112 -0
- data/ext/libtar/autom4te.cache/traces.0 +382 -0
- data/ext/libtar/compat/ChangeLog +31 -0
- data/ext/libtar/compat/README +12 -0
- data/ext/libtar/compat/TODO +4 -0
- data/ext/libtar/compat/basename.c +91 -0
- data/ext/libtar/compat/compat.h +260 -0
- data/ext/libtar/compat/dirname.c +96 -0
- data/ext/libtar/compat/fnmatch.c +237 -0
- data/ext/libtar/compat/gethostbyname_r.c +41 -0
- data/ext/libtar/compat/gethostname.c +36 -0
- data/ext/libtar/compat/getservbyname_r.c +41 -0
- data/ext/libtar/compat/glob.c +898 -0
- data/ext/libtar/compat/inet_aton.c +27 -0
- data/ext/libtar/compat/module.ac +591 -0
- data/ext/libtar/compat/snprintf.c +788 -0
- data/ext/libtar/compat/strdup.c +62 -0
- data/ext/libtar/compat/strlcat.c +72 -0
- data/ext/libtar/compat/strlcpy.c +68 -0
- data/ext/libtar/compat/strmode.c +199 -0
- data/ext/libtar/compat/strrstr.c +40 -0
- data/ext/libtar/compat/strsep.c +87 -0
- data/ext/libtar/config.h.in +187 -0
- data/ext/libtar/configure +8102 -0
- data/ext/libtar/configure.ac +114 -0
- data/ext/libtar/doc/Makefile.in +152 -0
- data/ext/libtar/doc/tar_append_file.3 +50 -0
- data/ext/libtar/doc/tar_block_read.3 +24 -0
- data/ext/libtar/doc/tar_extract_all.3 +43 -0
- data/ext/libtar/doc/tar_extract_file.3 +84 -0
- data/ext/libtar/doc/tar_open.3 +97 -0
- data/ext/libtar/doc/th_get_pathname.3 +63 -0
- data/ext/libtar/doc/th_print_long_ls.3 +22 -0
- data/ext/libtar/doc/th_read.3 +34 -0
- data/ext/libtar/doc/th_set_from_stat.3 +45 -0
- data/ext/libtar/lib/Makefile.in +92 -0
- data/ext/libtar/lib/append.c +272 -0
- data/ext/libtar/lib/block.c +384 -0
- data/ext/libtar/lib/decode.c +130 -0
- data/ext/libtar/lib/encode.c +237 -0
- data/ext/libtar/lib/extract.c +656 -0
- data/ext/libtar/lib/handle.c +150 -0
- data/ext/libtar/lib/internal.h +46 -0
- data/ext/libtar/lib/libtar.h +311 -0
- data/ext/libtar/lib/output.c +146 -0
- data/ext/libtar/lib/util.c +153 -0
- data/ext/libtar/lib/wrapper.c +175 -0
- data/ext/libtar/libtar/Makefile.in +73 -0
- data/ext/libtar/libtar/libtar.c +363 -0
- data/ext/libtar/listhash/ChangeLog +15 -0
- data/ext/libtar/listhash/TODO +21 -0
- data/ext/libtar/listhash/hash.c.in +344 -0
- data/ext/libtar/listhash/hash_new.3.in +74 -0
- data/ext/libtar/listhash/list.c.in +458 -0
- data/ext/libtar/listhash/list_new.3.in +86 -0
- data/ext/libtar/listhash/listhash.h.in +196 -0
- data/ext/libtar/listhash/module.ac +21 -0
- data/ext/libtar/win32/config.h +190 -0
- data/ext/libtar/win32/dirent.c +115 -0
- data/ext/libtar/win32/dirent.h +24 -0
- data/ext/libtar/win32/grp.h +4 -0
- data/ext/libtar/win32/listhash/libtar_hash.c +344 -0
- data/ext/libtar/win32/listhash/libtar_list.c +458 -0
- data/ext/libtar/win32/listhash/libtar_listhash.h +196 -0
- data/ext/libtar/win32/pwd.h +4 -0
- data/ext/libtar/win32/sys/param.h +8 -0
- data/ext/libtar/win32/tar.h +35 -0
- data/ext/libtar/win32/utime.h +6 -0
- data/ext/libtar/win32/win32/types.h +10 -0
- data/ext/tarruby.c +648 -0
- metadata +150 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
.TH th_set_from_stat 3 "Jan 2001" "University of Illinois" "C Library Calls"
|
2
|
+
.SH NAME
|
3
|
+
th_set_from_stat, th_finish, th_set_type, th_set_path, th_set_link, th_set_device, th_set_user, th_set_group, th_set_mode, th_set_mtime, th_set_size \- set fields of a tar file header
|
4
|
+
.SH SYNOPSIS
|
5
|
+
.B #include <libtar.h>
|
6
|
+
.P
|
7
|
+
.BI "void th_set_from_stat(TAR *" t ", struct stat *" s ");"
|
8
|
+
|
9
|
+
.BI "void th_set_type(TAR *" t ", mode_t " mode ");"
|
10
|
+
|
11
|
+
.BI "void th_set_path(TAR *" t ", char *" pathname ");"
|
12
|
+
|
13
|
+
.BI "void th_set_link(TAR *" t ", char *" linkname ");"
|
14
|
+
|
15
|
+
.BI "void th_set_device(TAR *" t ", dev_t " device ");"
|
16
|
+
|
17
|
+
.BI "void th_set_user(TAR *" t ", uid_t " uid ");"
|
18
|
+
|
19
|
+
.BI "void th_set_group(TAR *" t ", gid_t " gid ");"
|
20
|
+
|
21
|
+
.BI "void th_set_mode(TAR *" t ", mode_t " mode ");"
|
22
|
+
|
23
|
+
.BI "void th_set_mtime(TAR *" t ", time_t " fmtime ");"
|
24
|
+
|
25
|
+
.BI "void th_set_size(TAR *" t ", off_t " fsize ");"
|
26
|
+
|
27
|
+
.BI "void th_finish(TAR *" t ");"
|
28
|
+
.SH VERSION
|
29
|
+
This man page documents version 1.2 of \fBlibtar\fP.
|
30
|
+
.SH DESCRIPTION
|
31
|
+
The \fBth_set_*\fP() functions each set an individual field of the
|
32
|
+
current tar header associated with the \fITAR\fP handle \fIt\fP. The
|
33
|
+
\fBth_set_user\fP() and \fBth_set_group\fP() functions set both the
|
34
|
+
numeric user/group ID fields and the user/group name text fields.
|
35
|
+
The other functions set only the field that they refer to.
|
36
|
+
|
37
|
+
The \fBth_set_from_stat\fP() function uses the other \fBth_set_*\fP()
|
38
|
+
functions to set all of the fields at once, based on the data passed to
|
39
|
+
it in the argument \fIs\fP.
|
40
|
+
|
41
|
+
The \fBth_finish\fP() function sets the appropriate constants for the
|
42
|
+
magic and version fields. It then calculates the header checksum and
|
43
|
+
fills in the checksum field.
|
44
|
+
.SH SEE ALSO
|
45
|
+
.BR lstat (2)
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# @configure_input@
|
2
|
+
|
3
|
+
### Path settings
|
4
|
+
srcdir = @srcdir@
|
5
|
+
top_srcdir = @top_srcdir@
|
6
|
+
prefix = @prefix@
|
7
|
+
exec_prefix = @exec_prefix@
|
8
|
+
bindir = @bindir@
|
9
|
+
libdir = @libdir@
|
10
|
+
includedir = @includedir@
|
11
|
+
|
12
|
+
PACKAGE_NAME = @PACKAGE_NAME@
|
13
|
+
PACKAGE_VERSION = @PACKAGE_VERSION@
|
14
|
+
|
15
|
+
@ENCAP_DEFS@
|
16
|
+
|
17
|
+
### Installation programs and flags
|
18
|
+
INSTALL = @INSTALL@
|
19
|
+
INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s
|
20
|
+
INSTALL_DATA = @INSTALL_DATA@
|
21
|
+
LN_S = @LN_S@
|
22
|
+
MKDIR = @MKDIR@
|
23
|
+
|
24
|
+
### Compiler and link options
|
25
|
+
CC = @CC@
|
26
|
+
CPPFLAGS = -I. \
|
27
|
+
-I.. \
|
28
|
+
-I${srcdir} \
|
29
|
+
-I${top_srcdir}/compat \
|
30
|
+
-I../listhash \
|
31
|
+
@CPPFLAGS@
|
32
|
+
CFLAGS = @CFLAGS@
|
33
|
+
LDFLAGS = @LDFLAGS@
|
34
|
+
LIBS = @LIBS@
|
35
|
+
LIBOBJS = @LIBOBJS@
|
36
|
+
RANLIB = @RANLIB@
|
37
|
+
@SET_MAKE@
|
38
|
+
VPATH = @srcdir@:@top_srcdir@/compat:../listhash
|
39
|
+
|
40
|
+
|
41
|
+
### Makefile rules - no user-servicable parts below
|
42
|
+
|
43
|
+
LIBTAR_OBJS = append.o \
|
44
|
+
block.o \
|
45
|
+
decode.o \
|
46
|
+
encode.o \
|
47
|
+
extract.o \
|
48
|
+
handle.o \
|
49
|
+
libtar_hash.o \
|
50
|
+
libtar_list.o \
|
51
|
+
output.o \
|
52
|
+
util.o \
|
53
|
+
wrapper.o
|
54
|
+
LIBTAR_HDRS = ../config.h \
|
55
|
+
${top_srcdir}/compat/compat.h \
|
56
|
+
${srcdir}/libtar.h \
|
57
|
+
${srcdir}/internal.h \
|
58
|
+
../listhash/libtar_listhash.h
|
59
|
+
LIBTAR_LIBS = ./libtar.a
|
60
|
+
ALL = libtar.a
|
61
|
+
|
62
|
+
DISTCLEANFILES = ../listhash/libtar_listhash.h \
|
63
|
+
../listhash/libtar_list.c \
|
64
|
+
../listhash/libtar_hash.c
|
65
|
+
|
66
|
+
|
67
|
+
all: ${ALL}
|
68
|
+
|
69
|
+
.PHONY: clean distclean install
|
70
|
+
|
71
|
+
libtar.a: ${LIBTAR_OBJS} ${LIBOBJS}
|
72
|
+
${AR} rc libtar.a ${LIBTAR_OBJS} ${LIBOBJS}
|
73
|
+
${RANLIB} libtar.a
|
74
|
+
|
75
|
+
${LIBTAR_OBJS}: ${LIBTAR_HDRS}
|
76
|
+
|
77
|
+
.c.o:
|
78
|
+
${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
|
79
|
+
|
80
|
+
clean:
|
81
|
+
rm -f *~ *.o ${ALL} core
|
82
|
+
|
83
|
+
distclean: clean
|
84
|
+
rm -f Makefile ${DISTCLEANFILES}
|
85
|
+
|
86
|
+
install: ${ALL}
|
87
|
+
${MKDIR} ${DESTDIR}${libdir}
|
88
|
+
${INSTALL_DATA} libtar.a ${DESTDIR}${libdir}
|
89
|
+
${MKDIR} ${DESTDIR}${includedir}
|
90
|
+
${INSTALL_DATA} ${srcdir}/libtar.h ${DESTDIR}${includedir}
|
91
|
+
${INSTALL_DATA} ../listhash/libtar_listhash.h ${DESTDIR}${includedir}
|
92
|
+
|
@@ -0,0 +1,272 @@
|
|
1
|
+
/*
|
2
|
+
** Copyright 1998-2003 University of Illinois Board of Trustees
|
3
|
+
** Copyright 1998-2003 Mark D. Roth
|
4
|
+
** All rights reserved.
|
5
|
+
**
|
6
|
+
** append.c - libtar code to append files to a tar archive
|
7
|
+
**
|
8
|
+
** Mark D. Roth <roth@uiuc.edu>
|
9
|
+
** Campus Information Technologies and Educational Services
|
10
|
+
** University of Illinois at Urbana-Champaign
|
11
|
+
*/
|
12
|
+
|
13
|
+
// modified by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
14
|
+
#ifdef _WIN32
|
15
|
+
#pragma warning(disable:4101)
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#include <internal.h>
|
19
|
+
|
20
|
+
#include <stdio.h>
|
21
|
+
#include <errno.h>
|
22
|
+
#include <fcntl.h>
|
23
|
+
#include <sys/param.h>
|
24
|
+
#include <sys/types.h>
|
25
|
+
|
26
|
+
#ifdef STDC_HEADERS
|
27
|
+
# include <stdlib.h>
|
28
|
+
# include <string.h>
|
29
|
+
#endif
|
30
|
+
|
31
|
+
#ifdef HAVE_UNISTD_H
|
32
|
+
# include <unistd.h>
|
33
|
+
#endif
|
34
|
+
|
35
|
+
|
36
|
+
struct tar_dev
|
37
|
+
{
|
38
|
+
dev_t td_dev;
|
39
|
+
libtar_hash_t *td_h;
|
40
|
+
};
|
41
|
+
typedef struct tar_dev tar_dev_t;
|
42
|
+
|
43
|
+
struct tar_ino
|
44
|
+
{
|
45
|
+
ino_t ti_ino;
|
46
|
+
char ti_name[MAXPATHLEN];
|
47
|
+
};
|
48
|
+
typedef struct tar_ino tar_ino_t;
|
49
|
+
|
50
|
+
|
51
|
+
/* free memory associated with a tar_dev_t */
|
52
|
+
void
|
53
|
+
tar_dev_free(tar_dev_t *tdp)
|
54
|
+
{
|
55
|
+
libtar_hash_free(tdp->td_h, free);
|
56
|
+
free(tdp);
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
/* appends a file to the tar archive */
|
61
|
+
int
|
62
|
+
tar_append_file(TAR *t, char *realname, char *savename)
|
63
|
+
{
|
64
|
+
struct stat s;
|
65
|
+
int i;
|
66
|
+
libtar_hashptr_t hp;
|
67
|
+
tar_dev_t *td = NULL;
|
68
|
+
tar_ino_t *ti = NULL;
|
69
|
+
char path[MAXPATHLEN];
|
70
|
+
|
71
|
+
#ifdef DEBUG
|
72
|
+
printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
|
73
|
+
"savename=\"%s\")\n", t, t->pathname, realname,
|
74
|
+
(savename ? savename : "[NULL]"));
|
75
|
+
#endif
|
76
|
+
|
77
|
+
if (lstat(realname, &s) != 0)
|
78
|
+
{
|
79
|
+
#ifdef DEBUG
|
80
|
+
perror("lstat()");
|
81
|
+
#endif
|
82
|
+
return -1;
|
83
|
+
}
|
84
|
+
|
85
|
+
/* set header block */
|
86
|
+
#ifdef DEBUG
|
87
|
+
puts(" tar_append_file(): setting header block...");
|
88
|
+
#endif
|
89
|
+
memset(&(t->th_buf), 0, sizeof(struct tar_header));
|
90
|
+
th_set_from_stat(t, &s);
|
91
|
+
|
92
|
+
/* set the header path */
|
93
|
+
#ifdef DEBUG
|
94
|
+
puts(" tar_append_file(): setting header path...");
|
95
|
+
#endif
|
96
|
+
th_set_path(t, (savename ? savename : realname));
|
97
|
+
|
98
|
+
/* check if it's a hardlink */
|
99
|
+
#ifdef DEBUG
|
100
|
+
puts(" tar_append_file(): checking inode cache for hardlink...");
|
101
|
+
#endif
|
102
|
+
libtar_hashptr_reset(&hp);
|
103
|
+
if (libtar_hash_getkey(t->h, &hp, &(s.st_dev),
|
104
|
+
(libtar_matchfunc_t)dev_match) != 0)
|
105
|
+
td = (tar_dev_t *)libtar_hashptr_data(&hp);
|
106
|
+
else
|
107
|
+
{
|
108
|
+
#ifdef DEBUG
|
109
|
+
printf("+++ adding hash for device (0x%lx, 0x%lx)...\n",
|
110
|
+
major(s.st_dev), minor(s.st_dev));
|
111
|
+
#endif
|
112
|
+
td = (tar_dev_t *)calloc(1, sizeof(tar_dev_t));
|
113
|
+
td->td_dev = s.st_dev;
|
114
|
+
td->td_h = libtar_hash_new(256, (libtar_hashfunc_t)ino_hash);
|
115
|
+
if (td->td_h == NULL)
|
116
|
+
return -1;
|
117
|
+
if (libtar_hash_add(t->h, td) == -1)
|
118
|
+
return -1;
|
119
|
+
}
|
120
|
+
#ifndef _WIN32 // modified by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
121
|
+
libtar_hashptr_reset(&hp);
|
122
|
+
if (libtar_hash_getkey(td->td_h, &hp, &(s.st_ino),
|
123
|
+
(libtar_matchfunc_t)ino_match) != 0)
|
124
|
+
{
|
125
|
+
ti = (tar_ino_t *)libtar_hashptr_data(&hp);
|
126
|
+
#ifdef DEBUG
|
127
|
+
printf(" tar_append_file(): encoding hard link \"%s\" "
|
128
|
+
"to \"%s\"...\n", realname, ti->ti_name);
|
129
|
+
#endif
|
130
|
+
t->th_buf.typeflag = LNKTYPE;
|
131
|
+
th_set_link(t, ti->ti_name);
|
132
|
+
}
|
133
|
+
else
|
134
|
+
{
|
135
|
+
#ifdef DEBUG
|
136
|
+
printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
|
137
|
+
"(\"%s\")...\n", major(s.st_dev), minor(s.st_dev),
|
138
|
+
s.st_ino, realname);
|
139
|
+
#endif
|
140
|
+
ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t));
|
141
|
+
if (ti == NULL)
|
142
|
+
return -1;
|
143
|
+
ti->ti_ino = s.st_ino;
|
144
|
+
snprintf(ti->ti_name, sizeof(ti->ti_name), "%s",
|
145
|
+
savename ? savename : realname);
|
146
|
+
libtar_hash_add(td->td_h, ti);
|
147
|
+
}
|
148
|
+
#endif /* #ifndef _WIN32 */
|
149
|
+
|
150
|
+
#ifndef _WIN32 // modified by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
151
|
+
/* check if it's a symlink */
|
152
|
+
if (TH_ISSYM(t))
|
153
|
+
{
|
154
|
+
i = readlink(realname, path, sizeof(path));
|
155
|
+
if (i == -1)
|
156
|
+
return -1;
|
157
|
+
if (i >= MAXPATHLEN)
|
158
|
+
i = MAXPATHLEN - 1;
|
159
|
+
path[i] = '\0';
|
160
|
+
#ifdef DEBUG
|
161
|
+
printf(" tar_append_file(): encoding symlink \"%s\" -> "
|
162
|
+
"\"%s\"...\n", realname, path);
|
163
|
+
#endif
|
164
|
+
th_set_link(t, path);
|
165
|
+
}
|
166
|
+
#endif /* #ifndef _WIN32 */
|
167
|
+
|
168
|
+
/* print file info */
|
169
|
+
if (t->options & TAR_VERBOSE)
|
170
|
+
th_print_long_ls(t);
|
171
|
+
|
172
|
+
#ifdef DEBUG
|
173
|
+
puts(" tar_append_file(): writing header");
|
174
|
+
#endif
|
175
|
+
/* write header */
|
176
|
+
if (th_write(t) != 0)
|
177
|
+
{
|
178
|
+
#ifdef DEBUG
|
179
|
+
printf("t->fd = %d\n", t->fd);
|
180
|
+
#endif
|
181
|
+
return -1;
|
182
|
+
}
|
183
|
+
#ifdef DEBUG
|
184
|
+
puts(" tar_append_file(): back from th_write()");
|
185
|
+
#endif
|
186
|
+
|
187
|
+
/* if it's a regular file, write the contents as well */
|
188
|
+
if (TH_ISREG(t) && tar_append_regfile(t, realname) != 0)
|
189
|
+
return -1;
|
190
|
+
|
191
|
+
return 0;
|
192
|
+
}
|
193
|
+
|
194
|
+
|
195
|
+
/* write EOF indicator */
|
196
|
+
int
|
197
|
+
tar_append_eof(TAR *t)
|
198
|
+
{
|
199
|
+
int i, j;
|
200
|
+
char block[T_BLOCKSIZE];
|
201
|
+
|
202
|
+
memset(&block, 0, T_BLOCKSIZE);
|
203
|
+
for (j = 0; j < 2; j++)
|
204
|
+
{
|
205
|
+
i = tar_block_write(t, &block);
|
206
|
+
if (i != T_BLOCKSIZE)
|
207
|
+
{
|
208
|
+
if (i != -1)
|
209
|
+
errno = EINVAL;
|
210
|
+
return -1;
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
return 0;
|
215
|
+
}
|
216
|
+
|
217
|
+
|
218
|
+
/* add file contents to a tarchive */
|
219
|
+
int
|
220
|
+
tar_append_regfile(TAR *t, char *realname)
|
221
|
+
{
|
222
|
+
char block[T_BLOCKSIZE];
|
223
|
+
int filefd;
|
224
|
+
int i, j;
|
225
|
+
size_t size;
|
226
|
+
|
227
|
+
// modified by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
228
|
+
//filefd = open(realname, O_RDONLY);
|
229
|
+
filefd = open(realname, O_RDONLY
|
230
|
+
#ifdef O_BINARY
|
231
|
+
| O_BINARY
|
232
|
+
#endif
|
233
|
+
);
|
234
|
+
|
235
|
+
if (filefd == -1)
|
236
|
+
{
|
237
|
+
#ifdef DEBUG
|
238
|
+
perror("open()");
|
239
|
+
#endif
|
240
|
+
return -1;
|
241
|
+
}
|
242
|
+
|
243
|
+
size = th_get_size(t);
|
244
|
+
for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE)
|
245
|
+
{
|
246
|
+
j = read(filefd, &block, T_BLOCKSIZE);
|
247
|
+
if (j != T_BLOCKSIZE)
|
248
|
+
{
|
249
|
+
if (j != -1)
|
250
|
+
errno = EINVAL;
|
251
|
+
return -1;
|
252
|
+
}
|
253
|
+
if (tar_block_write(t, &block) == -1)
|
254
|
+
return -1;
|
255
|
+
}
|
256
|
+
|
257
|
+
if (i > 0)
|
258
|
+
{
|
259
|
+
j = read(filefd, &block, i);
|
260
|
+
if (j == -1)
|
261
|
+
return -1;
|
262
|
+
memset(&(block[i]), 0, T_BLOCKSIZE - i);
|
263
|
+
if (tar_block_write(t, &block) == -1)
|
264
|
+
return -1;
|
265
|
+
}
|
266
|
+
|
267
|
+
close(filefd);
|
268
|
+
|
269
|
+
return 0;
|
270
|
+
}
|
271
|
+
|
272
|
+
|