1 /*----------------------------------------------------------------------*\
2 |* spkg - The Unofficial Slackware Linux Package Manager *|
3 |* designed by Ondøej Jirman, 2005 *|
4 |*----------------------------------------------------------------------*|
5 |* No copy/usage restrictions are imposed on anybody. *|
6 \*----------------------------------------------------------------------*/
21 extern int link(const char *existing
, const char *newfile
);
25 ************************************************************************/
27 #define e_set(n, fmt, args...) e_add(_ta.err, "taction", __func__, n, fmt, ##args)
28 #define _e_set(e, n, fmt, args...) e_add(e, "taction", __func__, n, fmt, ##args)
38 static struct transaction _ta
= {
45 /* action list handling */
47 MOVE
, KEEP
, LINK
, FORCELINK
, SYMLINK
, CHPERM
, FORCESYMLINK
, REMOVE
,
62 static struct action
* _ta_insert(
68 g_assert(list
!= NULL
);
69 struct action
* a
= g_new0(struct action
, 1);
70 a
->on_finalize
= on_finalize
;
71 a
->on_rollback
= on_rollback
;
72 *list
= g_slist_prepend(*list
, a
);
76 static void _ta_free_action(struct action
* a
)
84 ************************************************************************/
86 gint
ta_initialize(gboolean dryrun
, struct error
* e
)
92 _e_set(e
, E_ERROR
|TA_ACTIVE
, "Can't start transaction while another transaction is still in progress.");
102 void ta_keep_remove(gchar
* path
, gboolean is_dir
)
105 struct action
* a
= _ta_insert(&_ta
.list
, KEEP
, REMOVE
);
110 void ta_move_remove(gchar
* path
, gchar
* dst_path
)
113 g_assert(dst_path
!= 0);
114 struct action
* a
= _ta_insert(&_ta
.list
, MOVE
, REMOVE
);
119 void ta_link_nothing(gchar
* path
, gchar
* tgt_path
)
122 g_assert(tgt_path
!= 0);
123 struct action
* a
= _ta_insert(&_ta
.list
, LINK
, NOTHING
);
128 void ta_symlink_nothing(gchar
* path
, gchar
* tgt_path
)
131 g_assert(tgt_path
!= 0);
132 struct action
* a
= _ta_insert(&_ta
.list
, SYMLINK
, NOTHING
);
137 void ta_forcesymlink_nothing(gchar
* path
, gchar
* tgt_path
)
140 g_assert(tgt_path
!= 0);
141 struct action
* a
= _ta_insert(&_ta
.list
, FORCESYMLINK
, NOTHING
);
146 void ta_forcelink_nothing(gchar
* path
, gchar
* tgt_path
)
149 g_assert(tgt_path
!= 0);
150 struct action
* a
= _ta_insert(&_ta
.list
, FORCELINK
, NOTHING
);
155 void ta_chperm_nothing(gchar
* path
, gint mode
, gint owner
, gint group
)
158 struct action
* a
= _ta_insert(&_ta
.list
, CHPERM
, NOTHING
);
165 void ta_remove_nothing(gchar
* path
, gint is_dir
)
170 struct action
* a
= _ta_insert(&_ta
.endlist
, REMOVE
, NOTHING
);
176 struct action
* a
= _ta_insert(&_ta
.list
, REMOVE
, NOTHING
);
188 e_set(E_ERROR
|TA_NACTIVE
, "Can't finalize transaction, because no transaction was started.");
192 _ta
.list
= g_slist_reverse(_ta
.list
);
193 for (l
=_ta
.list
; l
!=0; l
=l
->next
)
195 struct action
* a
= l
->data
;
196 if (a
->on_finalize
== MOVE
)
198 _debug("Moving %s -> %s", a
->path1
, a
->path2
);
202 if (access(a
->path2
, 0) == 0)
205 if (rename(a
->path1
, a
->path2
) == -1)
207 _warning("Failed to move %s -> %s (%s)", a
->path1
, a
->path2
, strerror(errno
));
211 else if (a
->on_finalize
== LINK
)
213 _notice("Creating hardlink %s -> %s", a
->path1
, a
->path2
);
216 if (link(a
->path2
, a
->path1
) == -1)
218 _warning("Failed to create hardlink %s -> %s (%s)", a
->path1
, a
->path2
, strerror(errno
));
222 else if (a
->on_finalize
== FORCELINK
)
224 _debug("Removing path %s", a
->path1
);
227 if (sys_rm_rf(a
->path1
))
229 _warning("Failed to remove path %s", a
->path1
);
233 _notice("Creating hardlink %s -> %s", a
->path1
, a
->path2
);
236 if (link(a
->path2
, a
->path1
) == -1)
238 _warning("Failed to create hardlink %s -> %s (%s)", a
->path1
, a
->path2
, strerror(errno
));
242 else if (a
->on_finalize
== SYMLINK
)
244 _notice("Creating symlink %s -> %s", a
->path1
, a
->path2
);
248 if (symlink(a
->path2
, a
->path1
) == -1)
250 _warning("Failed to create symlink %s -> %s (%s)", a
->path1
, a
->path2
, strerror(errno
));
253 _warning("Failed to create symlink %s -> %s (%s)", a
->path1
, a
->path2
, strerror(errno
));
257 else if (a
->on_finalize
== FORCESYMLINK
)
259 _debug("Removing path %s", a
->path1
);
262 if (sys_rm_rf(a
->path1
))
264 _warning("Failed to remove path %s", a
->path1
);
268 _notice("Creating symlink %s -> %s", a
->path1
, a
->path2
);
272 if (symlink(a
->path2
, a
->path1
) == -1)
274 _warning("Failed to create symlink %s -> %s (%s)", a
->path1
, a
->path2
, strerror(errno
));
277 _warning("Failed to create symlink %s -> %s (%s)", a
->path1
, a
->path2
, strerror(errno
));
281 else if (a
->on_finalize
== CHPERM
)
284 _notice("Changing mode on %s to %04o", a
->path1
, a
->mode
);
287 if (chmod(a
->path1
, a
->mode
) == -1)
289 _warning("Failed to cange mode on %s to %04o (%s)", a
->path1
, a
->mode
, strerror(errno
));
293 _notice("Changing owner on %s to %d:%d", a
->path1
, a
->owner
, a
->group
);
297 if (chown(a
->path1
, a
->owner
, a
->group
) == -1)
299 _warning("Failed to cange owner on %s to %d:%d (%s)", a
->path1
, a
->owner
, a
->group
, strerror(errno
));
304 else if (a
->on_finalize
== REMOVE
)
308 _notice("Removing file %s", a
->path1
);
311 if (unlink(a
->path1
))
313 _warning("Failed to remove file %s. (%s)", a
->path1
, strerror(errno
));
320 for (l
=_ta
.endlist
; l
!=0; l
=l
->next
)
322 struct action
* a
= l
->data
;
323 if (a
->on_finalize
== REMOVE
)
327 _notice("Removing directory %s", a
->path1
);
332 _warning("Failed to remove directory %s. (%s)", a
->path1
, strerror(errno
));
339 g_slist_foreach(_ta
.endlist
, (GFunc
)_ta_free_action
, 0);
340 g_slist_free(_ta
.endlist
);
341 g_slist_foreach(_ta
.list
, (GFunc
)_ta_free_action
, 0);
342 g_slist_free(_ta
.list
);
343 memset(&_ta
, 0, sizeof(_ta
));
353 e_set(E_ERROR
|TA_NACTIVE
, "Can't rollback transaction, because no transaction was started.");
357 for (l
=_ta
.list
; l
!=0; l
=l
->next
)
359 struct action
* a
= l
->data
;
360 if (a
->on_rollback
== REMOVE
)
364 _debug("Removing directory %s", a
->path1
);
367 if (rmdir(a
->path1
) == -1)
369 _warning("Failed to remove directory %s (%s)", a
->path1
, strerror(errno
));
375 _debug("Removing file %s", a
->path1
);
378 if (unlink(a
->path1
) == -1)
380 _warning("Failed to remove file %s (%s)", a
->path1
, strerror(errno
));
387 g_slist_foreach(_ta
.endlist
, (GFunc
)_ta_free_action
, 0);
388 g_slist_free(_ta
.endlist
);
389 g_slist_foreach(_ta
.list
, (GFunc
)_ta_free_action
, 0);
390 g_slist_free(_ta
.list
);
391 memset(&_ta
, 0, sizeof(_ta
));