2 This file is part of the KDE libraries
3 Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
9 This library 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 GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 #include <config-kstandarddirs.h>
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/socket.h>
39 int check_tmp_dir(const char *tmp_dir
, int check_ownership
);
40 int create_link(const char *file
, const char *tmp_dir
);
41 int build_link(const char* tmp
, const char *tmp_prefix
, const char *kde_prefix
);
43 /* checks that tmp_dir exists, otherwise creates it
44 * @param check_ownership: if 1, also check that user owns the dir
45 * returns 0 on success
47 int check_tmp_dir(const char *tmp_dir
, int check_ownership
)
49 /* reserve some space for an error string + a path name */
50 char errorstring
[PATH_MAX
+1024];
53 result
= lstat(tmp_dir
, &stat_buf
);
54 if ((result
== -1) && (errno
== ENOENT
))
57 result
= mkdir(tmp_dir
);
59 result
= mkdir(tmp_dir
, 0700);
63 snprintf(errorstring
, sizeof(errorstring
), "Error: cannot create directory \"%s\"", tmp_dir
);
67 result
= stat(tmp_dir
, &stat_buf
);
69 if ((result
== -1) || ( !S_ISDIR(stat_buf
.st_mode
) && !S_ISLNK(stat_buf
.st_mode
) ))
71 fprintf(stderr
, "Error: \"%s\" is not a directory.\n", tmp_dir
);
75 if (check_ownership
&& stat_buf
.st_uid
!= getuid())
77 fprintf(stderr
, "Error: \"%s\" is owned by uid %d instead of uid %d.\n", tmp_dir
, stat_buf
.st_uid
, getuid());
83 int create_link(const char *file
, const char *tmp_dir
)
86 result
= check_tmp_dir(tmp_dir
, 1);
91 result
= symlink(tmp_dir
, file
);
94 fprintf(stderr
, "Error: Can not create link from \"%s\" to \"%s\"\n", file
, tmp_dir
);
98 fprintf(stderr
,"Created link from \"%s\" to \"%s\"\n", file
, tmp_dir
);
104 int build_link(const char* tmp
, const char *tmp_prefix
, const char *kde_prefix
)
106 struct passwd
*pw_ent
;
107 char kde_tmp_dir
[PATH_MAX
+1];
108 char user_tmp_dir
[PATH_MAX
+1];
109 char tmp_buf
[PATH_MAX
+1];
111 const char *home_dir
= getenv("HOME");
112 const char *kde_home
= uid
? getenv("KDEHOME") : getenv("KDEROOTHOME");
114 struct stat stat_buf
;
118 pw_ent
= getpwuid(uid
);
121 fprintf(stderr
, "Error: Can not find password entry for uid %d.\n", getuid());
125 strncpy(user_tmp_dir
, tmp_prefix
, PATH_MAX
);
126 user_tmp_dir
[ PATH_MAX
] = '\0';
127 strncat(user_tmp_dir
, pw_ent
->pw_name
, PATH_MAX
- strlen(tmp_prefix
));
129 if (!kde_home
|| !kde_home
[0])
131 kde_home
= "~/" KDE_DEFAULT_HOME
"/";
134 if (kde_home
[0] == '~')
138 home_dir
= pw_ent
->pw_dir
? pw_ent
->pw_dir
: "/root";
140 if (!home_dir
|| !home_dir
[0])
142 fprintf(stderr
, "Aborting. $HOME not set!\n");
145 if (strlen(home_dir
) > (PATH_MAX
-100))
147 fprintf(stderr
, "Aborting. Home directory path too long!\n");
151 strncpy(kde_tmp_dir
, home_dir
, PATH_MAX
);
152 kde_tmp_dir
[ PATH_MAX
] = '\0';
154 strncat(kde_tmp_dir
, kde_home
, PATH_MAX
- strlen(kde_tmp_dir
));
156 /** Strip trailing '/' **/
157 if ( kde_tmp_dir
[strlen(kde_tmp_dir
)-1] == '/')
158 kde_tmp_dir
[strlen(kde_tmp_dir
)-1] = 0;
160 result
= stat(kde_tmp_dir
, &stat_buf
);
161 if ((result
== -1) && (errno
== ENOENT
))
164 result
= mkdir(kde_tmp_dir
);
166 result
= mkdir(kde_tmp_dir
, 0700);
171 perror("mkdir failed: ");
175 strncat(kde_tmp_dir
, kde_prefix
, PATH_MAX
- strlen(kde_tmp_dir
));
176 if (gethostname(kde_tmp_dir
+strlen(kde_tmp_dir
), PATH_MAX
- strlen(kde_tmp_dir
) - 1) != 0)
178 perror("Aborting. Could not determine hostname: ");
181 kde_tmp_dir
[sizeof(kde_tmp_dir
)-1] = '\0';
183 result
= lstat(kde_tmp_dir
, &stat_buf
);
184 if ((result
== 0) && (S_ISDIR(stat_buf
.st_mode
)))
186 /* $KDEHOME/tmp is a normal directory. Do nothing. */
188 fprintf(stderr
,"Directory \"%s\" already exists.\n", kde_tmp_dir
);
192 if ((result
== -1) && (errno
== ENOENT
))
195 fprintf(stderr
,"Creating link %s.\n", kde_tmp_dir
);
197 result
= create_link(kde_tmp_dir
, user_tmp_dir
);
198 if (result
== 0) return 0; /* Success */
200 strncat(user_tmp_dir
, "XXXXXX", PATH_MAX
- strlen(user_tmp_dir
));
202 mktemp(user_tmp_dir
); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
204 if (mkdtemp(user_tmp_dir
)==0) return 1; /*JOWENN: isn't that the better solution ?? */
206 return create_link(kde_tmp_dir
, user_tmp_dir
);
208 if ((result
== -1) || (!S_ISLNK(stat_buf
.st_mode
)))
210 fprintf(stderr
, "Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir
);
213 /* kde_tmp_dir is a link. Check whether it points to a valid directory. */
214 result
= readlink(kde_tmp_dir
, tmp_buf
, PATH_MAX
);
217 fprintf(stderr
, "Error: \"%s\" could not be read.\n", kde_tmp_dir
);
220 tmp_buf
[result
] = '\0';
222 fprintf(stderr
,"Link points to \"%s\"\n", tmp_buf
);
224 if (strncmp(tmp_buf
, user_tmp_dir
, strlen(user_tmp_dir
)) != 0)
226 fprintf(stderr
, "Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir
, tmp_buf
, user_tmp_dir
);
229 fprintf(stderr
, "Creating link %s.\n", kde_tmp_dir
);
231 result
= create_link(kde_tmp_dir
, user_tmp_dir
);
232 if (result
== 0) return 0; /* Success */
234 strncat(user_tmp_dir
, "XXXXXX", PATH_MAX
- strlen(user_tmp_dir
));
236 mktemp(user_tmp_dir
); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
238 if (mkdtemp(user_tmp_dir
)==0) return 1; /*JOWENN: isn't that the better solution ?? */
240 return create_link(kde_tmp_dir
, user_tmp_dir
);
242 result
= check_tmp_dir(tmp
, 0);
243 if (result
!= 0) return result
; /* Failure to create parent dir */
244 result
= check_tmp_dir(tmp_buf
, 1);
245 if (result
== 0) return 0; /* Success */
247 strncat(user_tmp_dir
, "XXXXXX", PATH_MAX
- strlen(user_tmp_dir
));
249 mktemp(user_tmp_dir
); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
251 if (mkdtemp(user_tmp_dir
)==0) return 1; /*JOWENN: isn't that the better solution ?? */
253 return create_link(kde_tmp_dir
, user_tmp_dir
);
256 int main(int argc
, char **argv
)
259 char *tmp_prefix
= 0;
260 const char *kde_prefix
= 0;
264 ((strcmp(argv
[1], "tmp")!=0) &&
265 (strcmp(argv
[1], "socket")!=0) &&
266 (strcmp(argv
[1], "cache")!=0)))
268 fprintf(stderr
, "Usage: lnusertemp tmp|socket|cache\n");
272 tmp
= getenv("KDETMP");
274 tmp
= getenv("TMPDIR");
278 if (strcmp(argv
[1], "tmp") == 0)
280 tmp_prefix
= (char *)malloc(strlen(tmp
)+strlen("/kde-")+1);
281 strcpy(tmp_prefix
, tmp
);
282 strcat(tmp_prefix
, "/kde-");
284 kde_prefix
= "/tmp-";
286 else if (strcmp(argv
[1], "socket") == 0)
288 tmp_prefix
= (char *)malloc(strlen(tmp
)+strlen("/ksocket-")+1);
289 strcpy(tmp_prefix
, tmp
);
290 strcat(tmp_prefix
, "/ksocket-" );
292 kde_prefix
= "/socket-";
294 else if (strcmp(argv
[1], "cache") == 0)
296 tmp
= getenv("KDEVARTMP");
300 tmp_prefix
= (char *)malloc(strlen(tmp
)+strlen("/kdecache-")+1);
301 strcpy(tmp_prefix
, tmp
);
302 strcat(tmp_prefix
, "/kdecache-" );
304 kde_prefix
= "/cache-";
307 res
= build_link(tmp
, tmp_prefix
, kde_prefix
);