@@ -260,47 +260,6 @@ void hyper_filize(char *hyper_path)
260260 }
261261}
262262
263- static int hyper_create_parent_dir (const char * hyper_path )
264- {
265- char * p , * path = strdup (hyper_path );
266- int ret = 0 ;
267-
268- if (path == NULL )
269- return -1 ;
270- p = strrchr (path , '/' );
271- if (p != NULL && p != path ) {
272- * p = '\0' ;
273- ret = hyper_mkdir (path , 0777 );
274- }
275- free (path );
276-
277- return ret ;
278- }
279-
280- /* hyper_path must point to a file rather than a directory, e.g., having trailing '/' */
281- int hyper_create_file (const char * hyper_path )
282- {
283- int fd ;
284- struct stat stbuf ;
285-
286- if (stat (hyper_path , & stbuf ) >= 0 ) {
287- if (S_ISREG (stbuf .st_mode ))
288- return 0 ;
289- errno = S_ISDIR (stbuf .st_mode ) ? EISDIR : EINVAL ;
290- return -1 ;
291- }
292-
293- if (hyper_create_parent_dir (hyper_path ) < 0 )
294- return -1 ;
295-
296- fd = open (hyper_path , O_CREAT |O_WRONLY , 0666 );
297- if (fd < 0 )
298- return -1 ;
299- close (fd );
300- fprintf (stdout , "created file %s\n" , hyper_path );
301- return 0 ;
302- }
303-
304263static char * hyper_resolve_link (char * path )
305264{
306265 char buf [512 ];
@@ -327,16 +286,17 @@ static char *hyper_resolve_link(char *path)
327286 * @root: chroot jail path.
328287 * @path: target directory. It is always relative to @root even if it starts with /.
329288 * @parent: what's already created to the target directory.
330- * @mode: directory mode.
331289 * @link_max: max number of symlinks to follow.
290+ * @create_file: create last component of @path as a normal file
332291 *
333292 * Upon success, @parent is changed to point to resolved path name.
334293 */
335294static int hyper_mkdir_follow_link (const char * root , const char * path , char * parent ,
336- mode_t mode , int * link_max )
295+ int * link_max , bool create_file )
337296{
338- char * comp , * prev , * link , * dummy , * npath , * delim = "/" ;
297+ char * comp , * next , * prev , * last , * link , * dummy , * npath , * delim = "/" ;
339298 struct stat st ;
299+ int fd ;
340300
341301 if (strncmp (root , parent , strlen (root )) != 0 ) {
342302 errno = EINVAL ;
@@ -352,6 +312,9 @@ static int hyper_mkdir_follow_link(const char *root, const char *path, char *par
352312 goto out ;
353313
354314 do {
315+ last = comp ;
316+ next = strtok_r (NULL , delim , & dummy );
317+
355318 if (!strcmp (comp , "." ))
356319 continue ;
357320
@@ -381,7 +344,8 @@ static int hyper_mkdir_follow_link(const char *root, const char *path, char *par
381344 strcat (parent , comp );
382345
383346 if (lstat (parent , & st ) >= 0 ) {
384- if (S_ISDIR (st .st_mode )) {
347+ if ((S_ISDIR (st .st_mode ) && (next != NULL || !create_file )) ||
348+ (S_ISREG (st .st_mode ) && next == NULL && create_file )) {
385349 continue ;
386350 } else if (S_ISLNK (st .st_mode )) {
387351 if (-- (* link_max ) <= 0 ) {
@@ -396,7 +360,7 @@ static int hyper_mkdir_follow_link(const char *root, const char *path, char *par
396360 } else {
397361 * prev = '\0' ; /* drop current comp */
398362 }
399- if (hyper_mkdir_follow_link (root , link , parent , mode , link_max ) < 0 ) {
363+ if (hyper_mkdir_follow_link (root , link , parent , link_max , next == NULL && create_file ) < 0 ) {
400364 free (link );
401365 goto out ;
402366 }
@@ -408,35 +372,38 @@ static int hyper_mkdir_follow_link(const char *root, const char *path, char *par
408372 }
409373 }
410374
411- fprintf (stdout , "create directory %s\n" , parent );
412- if (mkdir (parent , mode ) < 0 && errno != EEXIST ) {
413- perror ("failed to create directory" );
414- goto out ;
375+ if (next == NULL && create_file ) {
376+ fprintf (stdout , "create file %s\n" , parent );
377+ fd = open (parent , O_CREAT |O_WRONLY , 0666 );
378+ if (fd < 0 )
379+ goto out ;
380+ close (fd );
381+ } else {
382+ fprintf (stdout , "create directory %s\n" , parent );
383+ if (mkdir (parent , 0755 ) < 0 && errno != EEXIST ) {
384+ perror ("failed to create directory" );
385+ goto out ;
386+ }
415387 }
416- } while ((comp = strtok_r ( NULL , delim , & dummy ) ) != NULL );
388+ } while ((comp = next ) != NULL );
417389
418- /* reset errno to mark success */
419- errno = 0 ;
390+ if (create_file && (!strcmp (last , "." ) || !strcmp (last , ".." )))
391+ errno = ENOTDIR ;
392+ else
393+ /* reset errno to mark success */
394+ errno = 0 ;
420395out :
421396 free (npath );
422397 return errno ? -1 : 0 ;
423398}
424399
425- /*
426- * hyper_mkdir_at() is similar to hyper_mkdir() with the exception that
427- * when there are symlinks in the path components, it acts as if we created
428- * directories in a chroot jail. @hyper_path is always considered relative
429- * to root even if it starts with a leading stash ('/').
430- *
431- * Upon success, @hyper_path is modified to save resolved path in chroot jail.
432- */
433- int hyper_mkdir_at (const char * root , char * hyper_path , int size )
400+ static int hyper_create_target_at (const char * root , char * hyper_path , int size , bool create_file )
434401{
435402 char result [512 ];
436403 int max_link = 40 ;
437404
438405 sprintf (result , "%s" , root );
439- if (hyper_mkdir_follow_link (root , hyper_path , result , 0755 , & max_link ) < 0 )
406+ if (hyper_mkdir_follow_link (root , hyper_path , result , & max_link , create_file ) < 0 )
440407 return -1 ;
441408
442409 if (strlen (result ) + 1 > size ) {
@@ -447,6 +414,33 @@ int hyper_mkdir_at(const char *root, char *hyper_path, int size)
447414 return 0 ;
448415}
449416
417+ /*
418+ * hyper_mkdir_at() is similar to hyper_mkdir() with the exception that
419+ * when there are symlinks in the path components, it acts as if we created
420+ * directories in a chroot jail. @hyper_path is always considered relative
421+ * to root even if it starts with a leading stash ('/').
422+ *
423+ * Upon success, @hyper_path is modified to save resolved path in chroot jail.
424+ */
425+ int hyper_mkdir_at (const char * root , char * hyper_path , int size )
426+ {
427+ return hyper_create_target_at (root , hyper_path , size , false);
428+ }
429+
430+ /**
431+ * hyper_create_file_at - create a file in @root chroot jail.
432+ *
433+ * @root: chroot jail path.
434+ * @hyper_path: must point to a file rather than a directory, e.g., having trailing '/'
435+ * @size: size of @hyper_path storage.
436+ *
437+ * Upon success, @hyper_path is modified to point to the path resolved in chroot jail.
438+ */
439+ int hyper_create_file_at (const char * root , char * hyper_path , int size )
440+ {
441+ return hyper_create_target_at (root , hyper_path , size , true);
442+ }
443+
450444int hyper_mkdir (char * path , mode_t mode )
451445{
452446 struct stat st ;
0 commit comments