1/* addext.c -- add an extension to a file name
2   Copyright (C) 1990, 1997-1999, 2001-2003 Free Software Foundation, Inc.
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2, or (at your option)
7   any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program; see the file COPYING.
16   If not, write to the Free Software Foundation,
17   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19/* Written by David MacKenzie <djm@gnu.ai.mit.edu> and Paul Eggert */
20
21#if HAVE_CONFIG_H
22# include <config.h>
23#endif
24
25#ifndef HAVE_DOS_FILE_NAMES
26# define HAVE_DOS_FILE_NAMES 0
27#endif
28#ifndef HAVE_LONG_FILE_NAMES
29# define HAVE_LONG_FILE_NAMES 0
30#endif
31
32#include "backupfile.h"
33
34#include <limits.h>
35#ifndef _POSIX_NAME_MAX
36# define _POSIX_NAME_MAX 14
37#endif
38
39#include <sys/types.h>
40#if HAVE_STRING_H
41# include <string.h>
42#else
43# include <strings.h>
44#endif
45
46#if HAVE_UNISTD_H
47# include <unistd.h>
48#endif
49
50#include "basename.h"
51
52/* Append to FILENAME the extension EXT, unless the result would be too long,
53   in which case just append the character E.  */
54
55void
56addext (char *filename, char const *ext, char e)
57{
58  char *s = basename (filename);
59  size_t slen = strlen (s), extlen = strlen (ext);
60  long slen_max = -1;
61
62#if HAVE_PATHCONF && defined _PC_NAME_MAX
63  if (slen + extlen <= _POSIX_NAME_MAX && ! HAVE_DOS_FILE_NAMES)
64    /* The file name is so short there's no need to call pathconf.  */
65    slen_max = _POSIX_NAME_MAX;
66  else if (s == filename)
67    slen_max = pathconf (".", _PC_NAME_MAX);
68  else
69    {
70      char c = *s;
71      *s = 0;
72      slen_max = pathconf (filename, _PC_NAME_MAX);
73      *s = c;
74    }
75#endif
76  if (slen_max < 0)
77    slen_max = HAVE_LONG_FILE_NAMES ? 255 : 14;
78
79  if (HAVE_DOS_FILE_NAMES && slen_max <= 12)
80    {
81      /* Live within DOS's 8.3 limit.  */
82      char *dot = strchr (s, '.');
83      if (dot)
84	{
85	  slen -= dot + 1 - s;
86	  s = dot + 1;
87	  slen_max = 3;
88	}
89      else
90	slen_max = 8;
91      extlen = 9; /* Don't use EXT.  */
92    }
93
94  if (slen + extlen <= slen_max)
95    strcpy (s + slen, ext);
96  else
97    {
98      if (slen_max <= slen)
99	slen = slen_max - 1;
100      s[slen] = e;
101      s[slen + 1] = 0;
102    }
103}
104