2 This file is part of mktorrent
3 Copyright (C) 2007, 2009 Emil Renner Berthing
5 mktorrent is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mktorrent is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <sys/types.h> /* off_t */
21 #include <stdio.h> /* printf() etc. */
22 #include <string.h> /* strlen() etc. */
23 #include <time.h> /* time() */
25 #include <openssl/sha.h> /* SHA_DIGEST_LENGTH */
31 #include "mktorrent.h"
39 static void write_announce_list(FILE *f
, llist_t
*list
)
41 /* the announce list is a list of lists of urls */
42 fprintf(f
, "13:announce-listl");
43 /* go through them all.. */
44 for (; list
; list
= list
->next
) {
47 /* .. and print the lists */
49 for (l
= list
->l
; l
; l
= l
->next
)
51 (unsigned long)strlen(l
->s
), l
->s
);
60 static void write_file_list(FILE *f
, flist_t
*list
)
64 fprintf(f
, "5:filesl");
66 /* go through all the files */
67 for (; list
; list
= list
->next
) {
68 /* the file list contains a dictionary for every file
69 with entries for the length and path
70 write the length first */
71 fprintf(f
, "d4:hash8:%s6:lengthi%" PRIoff
"e4:pathl",list
->hash
, list
->size
);
72 /* the file path is written as a list of subdirectories
73 and the last entry is the filename
74 sorry this code is even uglier than the rest */
76 /* while there are subdirectories before the filename.. */
77 while ((b
= strchr(a
, DIRSEP_CHAR
)) != NULL
) {
78 /* set the next DIRSEP_CHAR to '\0' so fprintf
79 will only write the first subdirectory name */
81 /* print it bencoded */
82 fprintf(f
, "%lu:%s", (unsigned long)strlen(a
), a
);
83 /* undo our alteration to the string */
85 /* and move a to the beginning of the next
89 /* now print the filename bencoded and end the
90 path name list and file dictionary */
91 fprintf(f
, "%lu:%see", (unsigned long)strlen(a
), a
);
94 /* whew, now end the file list */
101 static void write_web_seed_list(FILE *f
, slist_t
*list
)
103 /* print the entry and start the list */
104 fprintf(f
, "8:url-listl");
105 /* go through the list and write each URL */
106 for (; list
; list
= list
->next
)
107 fprintf(f
, "%lu:%s", (unsigned long)strlen(list
->s
), list
->s
);
113 * write metainfo to the file stream using all the information
114 * we've gathered so far and the hash string calculated
116 EXPORT
void write_metainfo(FILE *f
, metafile_t
*m
, unsigned char *hash_string
)
118 /* let the user know we've started writing the metainfo file */
119 printf("Writing metainfo file... ");
122 /* every metainfo file is one big dictonary
123 and the first entry is the announce URL */
124 fprintf(f
, "d8:announce%lu:%s",
125 (unsigned long)strlen(m
->announce_list
->l
->s
),
126 m
->announce_list
->l
->s
);
127 /* write the announce-list entry if we have
128 more than one announce URL */
129 if (m
->announce_list
->next
|| m
->announce_list
->l
->next
)
130 write_announce_list(f
, m
->announce_list
);
131 /* add the comment if one is specified */
132 if (m
->comment
!= NULL
)
133 fprintf(f
, "7:comment%lu:%s",
134 (unsigned long)strlen(m
->comment
),
137 fprintf(f
, "10:created by17:mktorrent_crc 0.2");
138 /* add the creation date */
139 if (!m
->no_creation_date
)
140 fprintf(f
, "13:creation datei%lde",
143 /* now here comes the info section
144 it is yet another dictionary */
145 fprintf(f
, "4:infod");
146 /* first entry is either 'length', which specifies the length of a
147 single file torrent, or a list of files and their respective sizes */
148 if (!m
->target_is_directory
)
149 fprintf(f
, "6:lengthi%" PRIoff
"e", m
->file_list
->size
);
151 write_file_list(f
, m
->file_list
);
153 /* the info section also contains the name of the torrent,
154 the piece length and the hash string */
155 fprintf(f
, "4:name%lu:%s12:piece lengthi%ue6:pieces%u:",
156 (unsigned long)strlen(m
->torrent_name
), m
->torrent_name
,
157 m
->piece_length
, m
->pieces
* SHA_DIGEST_LENGTH
);
158 fwrite(hash_string
, 1, m
->pieces
* SHA_DIGEST_LENGTH
, f
);
160 /* set the private flag */
162 fprintf(f
, "7:privatei1e");
164 /* end the info section */
167 /* add url-list if one is specified */
168 if (m
->web_seed_list
!= NULL
) {
169 if (m
->web_seed_list
->next
== NULL
)
170 fprintf(f
, "8:url-list%lu:%s",
171 (unsigned long)strlen(m
->web_seed_list
->s
),
172 m
->web_seed_list
->s
);
174 write_web_seed_list(f
, m
->web_seed_list
);
177 /* end the root dictionary */
180 /* let the user know we're done already */